mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-11 11:42:12 +02:00
test
type safe view access
This commit is contained in:
parent
4197921465
commit
4fe512ff3a
pkg/gui
branches_panel.gocherry_picking.gocommit_files_panel.gocommit_message_panel.gocommits_panel.goconfirmation_panel.gocontext.gocredentials_panel.gocustom_commands.godiffing.gofiles_panel.goglobal_handlers.gogui.gokeybindings.golayout.goline_by_line_panel.golist_context.gomain_panels.gomenu_panel.gomerge_panel.gopatch_building_panel.gopty.gorecent_repos_panel.goreflog_panel.goremote_branches_panel.goremotes_panel.gosearching.goside_window.gostaging_panel.gostash_panel.gostatus_panel.gosub_commits_panel.gosubmodules_panel.gosuggestions_panel.gotags_panel.goview_helpers.go
@ -30,13 +30,13 @@ func (gui *Gui) handleBranchSelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
branch := gui.getSelectedBranch()
|
branch := gui.getSelectedBranch()
|
||||||
if branch == nil {
|
if branch == nil {
|
||||||
task = gui.createRenderStringTask(gui.Tr.NoBranchesThisRepo)
|
task = NewRenderStringTask(gui.Tr.NoBranchesThisRepo)
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.GetBranchGraphCmdStr(branch.Name),
|
gui.GitCommand.GetBranchGraphCmdStr(branch.Name),
|
||||||
)
|
)
|
||||||
|
|
||||||
task = gui.createRunPtyTask(cmd)
|
task = NewRunPtyTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
@ -473,7 +473,7 @@ func (gui *Gui) currentBranch() *models.Branch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleNewBranchOffCurrentItem() error {
|
func (gui *Gui) handleNewBranchOffCurrentItem() error {
|
||||||
context := gui.currentSideContext()
|
context := gui.currentSideListContext()
|
||||||
|
|
||||||
item, ok := context.GetSelectedItem()
|
item, ok := context.GetSelectedItem()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -24,7 +24,7 @@ func (gui *Gui) handleCopyCommit() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get currently selected commit, add the sha to state.
|
// get currently selected commit, add the sha to state.
|
||||||
context := gui.currentSideContext()
|
context := gui.currentSideListContext()
|
||||||
if context == nil {
|
if context == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ func (gui *Gui) cherryPickedCommitShaMap() map[string]bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) commitsListForContext() []*models.Commit {
|
func (gui *Gui) commitsListForContext() []*models.Commit {
|
||||||
context := gui.currentSideContext()
|
context := gui.currentSideListContext()
|
||||||
if context == nil {
|
if context == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ func (gui *Gui) handleCopyCommitRange() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get currently selected commit, add the sha to state.
|
// get currently selected commit, add the sha to state.
|
||||||
context := gui.currentSideContext()
|
context := gui.currentSideListContext()
|
||||||
if context == nil {
|
if context == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ func (gui *Gui) exitCherryPickingMode() error {
|
|||||||
return gui.rerenderContextViewIfPresent(contextKey)
|
return gui.rerenderContextViewIfPresent(contextKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) rerenderContextViewIfPresent(contextKey string) error {
|
func (gui *Gui) rerenderContextViewIfPresent(contextKey ContextKey) error {
|
||||||
if contextKey == "" {
|
if contextKey == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ func (gui *Gui) rerenderContextViewIfPresent(contextKey string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if view.Context == contextKey {
|
if ContextKey(view.Context) == contextKey {
|
||||||
if err := context.HandleRender(); err != nil {
|
if err := context.HandleRender(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func (gui *Gui) handleCommitFileSelect() error {
|
|||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.ShowFileDiffCmdStr(from, to, reverse, node.GetPath(), false),
|
gui.GitCommand.ShowFileDiffCmdStr(from, to, reverse, node.GetPath(), false),
|
||||||
)
|
)
|
||||||
task := gui.createRunPtyTask(cmd)
|
task := NewRunPtyTask(cmd)
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
@ -287,7 +287,8 @@ func (gui *Gui) handleToggleCommitFileTreeView() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.getCommitFilesView().Context == COMMIT_FILES_CONTEXT_KEY {
|
// TODO: pretty sure this view only ever has this context. Is this if condition necessary?
|
||||||
|
if gui.Views.CommitFiles.Context == COMMIT_FILES_CONTEXT_KEY {
|
||||||
if err := gui.State.Contexts.CommitFiles.HandleRender(); err != nil {
|
if err := gui.State.Contexts.CommitFiles.HandleRender(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,7 @@ func (gui *Gui) runSyncOrAsyncCommand(sub *exec.Cmd, err error) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleCommitConfirm() error {
|
func (gui *Gui) handleCommitConfirm() error {
|
||||||
commitMessageView := gui.getCommitMessageView()
|
message := gui.trimmedContent(gui.Views.CommitMessage)
|
||||||
message := gui.trimmedContent(commitMessageView)
|
|
||||||
if message == "" {
|
if message == "" {
|
||||||
return gui.createErrorPanel(gui.Tr.CommitWithoutMessageErr)
|
return gui.createErrorPanel(gui.Tr.CommitWithoutMessageErr)
|
||||||
}
|
}
|
||||||
@ -41,7 +40,7 @@ func (gui *Gui) handleCommitConfirm() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.clearEditorView(commitMessageView)
|
gui.clearEditorView(gui.Views.CommitMessage)
|
||||||
_ = gui.returnFromContext()
|
_ = gui.returnFromContext()
|
||||||
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
|
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
|
||||||
}
|
}
|
||||||
@ -73,6 +72,6 @@ func (gui *Gui) RenderCommitLength() {
|
|||||||
if !gui.Config.GetUserConfig().Gui.CommitLength.Show {
|
if !gui.Config.GetUserConfig().Gui.CommitLength.Show {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v := gui.getCommitMessageView()
|
|
||||||
v.Subtitle = gui.getBufferLength(v)
|
gui.Views.CommitMessage.Subtitle = gui.getBufferLength(gui.Views.CommitMessage)
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,12 @@ func (gui *Gui) handleCommitSelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
commit := gui.getSelectedLocalCommit()
|
commit := gui.getSelectedLocalCommit()
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
task = gui.createRenderStringTask(gui.Tr.NoCommitsThisBranch)
|
task = NewRenderStringTask(gui.Tr.NoCommitsThisBranch)
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
||||||
)
|
)
|
||||||
task = gui.createRunPtyTask(cmd)
|
task = NewRunPtyTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
|
@ -108,19 +108,17 @@ func (gui *Gui) wrappedPromptConfirmationFunction(handlersManageFocus bool, func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) deleteConfirmationView() {
|
func (gui *Gui) clearConfirmationViewKeyBindings() {
|
||||||
keybindingConfig := gui.Config.GetUserConfig().Keybinding
|
keybindingConfig := gui.Config.GetUserConfig().Keybinding
|
||||||
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone)
|
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone)
|
||||||
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone)
|
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone)
|
||||||
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone)
|
_ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone)
|
||||||
|
|
||||||
_ = gui.g.DeleteView("confirmation")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) closeConfirmationPrompt(handlersManageFocus bool) error {
|
func (gui *Gui) closeConfirmationPrompt(handlersManageFocus bool) error {
|
||||||
view := gui.getConfirmationView()
|
// we've already closed it so we can just return
|
||||||
if view == nil {
|
if !gui.Views.Confirmation.Visible {
|
||||||
return nil // if it's already been closed we can just return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !handlersManageFocus {
|
if !handlersManageFocus {
|
||||||
@ -129,9 +127,9 @@ func (gui *Gui) closeConfirmationPrompt(handlersManageFocus bool) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.deleteConfirmationView()
|
gui.clearConfirmationViewKeyBindings()
|
||||||
|
gui.Views.Confirmation.Visible = false
|
||||||
_, _ = gui.g.SetViewOnBottom("suggestions")
|
gui.Views.Suggestions.Visible = false
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -200,7 +198,7 @@ func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool, f
|
|||||||
suggestionsView.FgColor = theme.GocuiDefaultTextColor
|
suggestionsView.FgColor = theme.GocuiDefaultTextColor
|
||||||
}
|
}
|
||||||
gui.setSuggestions([]*types.Suggestion{})
|
gui.setSuggestions([]*types.Suggestion{})
|
||||||
_, _ = gui.g.SetViewOnTop("suggestions")
|
suggestionsView.Visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.g.Update(func(g *gocui.Gui) error {
|
gui.g.Update(func(g *gocui.Gui) error {
|
||||||
@ -211,10 +209,9 @@ func (gui *Gui) prepareConfirmationPanel(title, prompt string, hasLoader bool, f
|
|||||||
|
|
||||||
func (gui *Gui) createPopupPanel(opts createPopupPanelOpts) error {
|
func (gui *Gui) createPopupPanel(opts createPopupPanelOpts) error {
|
||||||
gui.g.Update(func(g *gocui.Gui) error {
|
gui.g.Update(func(g *gocui.Gui) error {
|
||||||
// delete the existing confirmation panel if it exists
|
// remove any previous keybindings
|
||||||
if view, _ := g.View("confirmation"); view != nil {
|
gui.clearConfirmationViewKeyBindings()
|
||||||
gui.deleteConfirmationView()
|
|
||||||
}
|
|
||||||
confirmationView, err := gui.prepareConfirmationPanel(opts.title, opts.prompt, opts.hasLoader, opts.findSuggestionsFunc)
|
confirmationView, err := gui.prepareConfirmationPanel(opts.title, opts.prompt, opts.hasLoader, opts.findSuggestionsFunc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -251,7 +248,7 @@ func (gui *Gui) setKeyBindings(opts createPopupPanelOpts) error {
|
|||||||
gui.renderString("options", actions)
|
gui.renderString("options", actions)
|
||||||
var onConfirm func() error
|
var onConfirm func() error
|
||||||
if opts.handleConfirmPrompt != nil {
|
if opts.handleConfirmPrompt != nil {
|
||||||
onConfirm = gui.wrappedPromptConfirmationFunction(opts.handlersManageFocus, opts.handleConfirmPrompt, func() string { return gui.getConfirmationView().Buffer() })
|
onConfirm = gui.wrappedPromptConfirmationFunction(opts.handlersManageFocus, opts.handleConfirmPrompt, func() string { return gui.Views.Confirmation.Buffer() })
|
||||||
} else {
|
} else {
|
||||||
onConfirm = gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleConfirm)
|
onConfirm = gui.wrappedConfirmationFunction(opts.handlersManageFocus, opts.handleConfirm)
|
||||||
}
|
}
|
||||||
|
@ -15,32 +15,34 @@ const (
|
|||||||
PERSISTENT_POPUP
|
PERSISTENT_POPUP
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ContextKey string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
STATUS_CONTEXT_KEY = "status"
|
STATUS_CONTEXT_KEY ContextKey = "status"
|
||||||
FILES_CONTEXT_KEY = "files"
|
FILES_CONTEXT_KEY = "files"
|
||||||
LOCAL_BRANCHES_CONTEXT_KEY = "localBranches"
|
LOCAL_BRANCHES_CONTEXT_KEY = "localBranches"
|
||||||
REMOTES_CONTEXT_KEY = "remotes"
|
REMOTES_CONTEXT_KEY = "remotes"
|
||||||
REMOTE_BRANCHES_CONTEXT_KEY = "remoteBranches"
|
REMOTE_BRANCHES_CONTEXT_KEY = "remoteBranches"
|
||||||
TAGS_CONTEXT_KEY = "tags"
|
TAGS_CONTEXT_KEY = "tags"
|
||||||
BRANCH_COMMITS_CONTEXT_KEY = "commits"
|
BRANCH_COMMITS_CONTEXT_KEY = "commits"
|
||||||
REFLOG_COMMITS_CONTEXT_KEY = "reflogCommits"
|
REFLOG_COMMITS_CONTEXT_KEY = "reflogCommits"
|
||||||
SUB_COMMITS_CONTEXT_KEY = "subCommits"
|
SUB_COMMITS_CONTEXT_KEY = "subCommits"
|
||||||
COMMIT_FILES_CONTEXT_KEY = "commitFiles"
|
COMMIT_FILES_CONTEXT_KEY = "commitFiles"
|
||||||
STASH_CONTEXT_KEY = "stash"
|
STASH_CONTEXT_KEY = "stash"
|
||||||
MAIN_NORMAL_CONTEXT_KEY = "normal"
|
MAIN_NORMAL_CONTEXT_KEY = "normal"
|
||||||
MAIN_MERGING_CONTEXT_KEY = "merging"
|
MAIN_MERGING_CONTEXT_KEY = "merging"
|
||||||
MAIN_PATCH_BUILDING_CONTEXT_KEY = "patchBuilding"
|
MAIN_PATCH_BUILDING_CONTEXT_KEY = "patchBuilding"
|
||||||
MAIN_STAGING_CONTEXT_KEY = "staging"
|
MAIN_STAGING_CONTEXT_KEY = "staging"
|
||||||
MENU_CONTEXT_KEY = "menu"
|
MENU_CONTEXT_KEY = "menu"
|
||||||
CREDENTIALS_CONTEXT_KEY = "credentials"
|
CREDENTIALS_CONTEXT_KEY = "credentials"
|
||||||
CONFIRMATION_CONTEXT_KEY = "confirmation"
|
CONFIRMATION_CONTEXT_KEY = "confirmation"
|
||||||
SEARCH_CONTEXT_KEY = "search"
|
SEARCH_CONTEXT_KEY = "search"
|
||||||
COMMIT_MESSAGE_CONTEXT_KEY = "commitMessage"
|
COMMIT_MESSAGE_CONTEXT_KEY = "commitMessage"
|
||||||
SUBMODULES_CONTEXT_KEY = "submodules"
|
SUBMODULES_CONTEXT_KEY = "submodules"
|
||||||
SUGGESTIONS_CONTEXT_KEY = "suggestions"
|
SUGGESTIONS_CONTEXT_KEY = "suggestions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allContextKeys = []string{
|
var allContextKeys = []ContextKey{
|
||||||
STATUS_CONTEXT_KEY,
|
STATUS_CONTEXT_KEY,
|
||||||
FILES_CONTEXT_KEY,
|
FILES_CONTEXT_KEY,
|
||||||
LOCAL_BRANCHES_CONTEXT_KEY,
|
LOCAL_BRANCHES_CONTEXT_KEY,
|
||||||
@ -124,7 +126,7 @@ type Context interface {
|
|||||||
GetViewName() string
|
GetViewName() string
|
||||||
GetWindowName() string
|
GetWindowName() string
|
||||||
SetWindowName(string)
|
SetWindowName(string)
|
||||||
GetKey() string
|
GetKey() ContextKey
|
||||||
SetParentContext(Context)
|
SetParentContext(Context)
|
||||||
|
|
||||||
// we return a bool here to tell us whether or not the returned value just wraps a nil
|
// we return a bool here to tell us whether or not the returned value just wraps a nil
|
||||||
@ -138,7 +140,7 @@ type BasicContext struct {
|
|||||||
OnRender func() error
|
OnRender func() error
|
||||||
OnGetOptionsMap func() map[string]string
|
OnGetOptionsMap func() map[string]string
|
||||||
Kind ContextKind
|
Kind ContextKind
|
||||||
Key string
|
Key ContextKey
|
||||||
ViewName string
|
ViewName string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +194,7 @@ func (c BasicContext) GetKind() ContextKind {
|
|||||||
return c.Kind
|
return c.Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c BasicContext) GetKey() string {
|
func (c BasicContext) GetKey() ContextKey {
|
||||||
return c.Key
|
return c.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,7 +355,7 @@ func (tree ContextTree) initialViewTabContextMap() map[string][]tabContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) currentContextKeyIgnoringPopups() string {
|
func (gui *Gui) currentContextKeyIgnoringPopups() ContextKey {
|
||||||
gui.State.ContextManager.Lock()
|
gui.State.ContextManager.Lock()
|
||||||
defer gui.State.ContextManager.Unlock()
|
defer gui.State.ContextManager.Unlock()
|
||||||
|
|
||||||
@ -461,7 +463,10 @@ func (gui *Gui) returnFromContext() error {
|
|||||||
func (gui *Gui) deactivateContext(c Context) error {
|
func (gui *Gui) deactivateContext(c Context) error {
|
||||||
// if we are the kind of context that is sent to back upon deactivation, we should do that
|
// if we are the kind of context that is sent to back upon deactivation, we should do that
|
||||||
if c.GetKind() == TEMPORARY_POPUP || c.GetKind() == PERSISTENT_POPUP || c.GetKey() == COMMIT_FILES_CONTEXT_KEY {
|
if c.GetKind() == TEMPORARY_POPUP || c.GetKind() == PERSISTENT_POPUP || c.GetKey() == COMMIT_FILES_CONTEXT_KEY {
|
||||||
_, _ = gui.g.SetViewOnBottom(c.GetViewName())
|
view, err := gui.g.View(c.GetViewName())
|
||||||
|
if err == nil {
|
||||||
|
view.Visible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.HandleFocusLost(); err != nil {
|
if err := c.HandleFocusLost(); err != nil {
|
||||||
@ -480,7 +485,7 @@ func (gui *Gui) postRefreshUpdate(c Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Context != c.GetKey() {
|
if ContextKey(v.Context) != c.GetKey() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +509,7 @@ func (gui *Gui) activateContext(c Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return gui.returnFromContext()
|
return gui.returnFromContext()
|
||||||
}
|
}
|
||||||
originalViewContextKey := v.Context
|
originalViewContextKey := ContextKey(v.Context)
|
||||||
|
|
||||||
// ensure that any other window for which this view was active is now set to the default for that window.
|
// ensure that any other window for which this view was active is now set to the default for that window.
|
||||||
gui.setViewAsActiveForWindow(viewName)
|
gui.setViewAsActiveForWindow(viewName)
|
||||||
@ -522,10 +527,7 @@ func (gui *Gui) activateContext(c Context) error {
|
|||||||
return gui.returnFromContext()
|
return gui.returnFromContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := gui.g.SetViewOnTop(viewName); err != nil {
|
v.Visible = true
|
||||||
// if view no longer exists, pop again
|
|
||||||
return gui.returnFromContext()
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the new context's view was previously displaying another context, render the new context
|
// if the new context's view was previously displaying another context, render the new context
|
||||||
if originalViewContextKey != c.GetKey() {
|
if originalViewContextKey != c.GetKey() {
|
||||||
@ -534,7 +536,7 @@ func (gui *Gui) activateContext(c Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Context = c.GetKey()
|
v.Context = string(c.GetKey())
|
||||||
|
|
||||||
gui.g.Cursor = v.Editable
|
gui.g.Cursor = v.Editable
|
||||||
|
|
||||||
@ -559,7 +561,7 @@ func (gui *Gui) activateContext(c Context) error {
|
|||||||
func (gui *Gui) renderContextStack() string {
|
func (gui *Gui) renderContextStack() string {
|
||||||
result := ""
|
result := ""
|
||||||
for _, context := range gui.State.ContextManager.ContextStack {
|
for _, context := range gui.State.ContextManager.ContextStack {
|
||||||
result += context.GetKey() + "\n"
|
result += string(context.GetKey()) + "\n"
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -575,7 +577,18 @@ func (gui *Gui) currentContext() Context {
|
|||||||
return gui.State.ContextManager.ContextStack[len(gui.State.ContextManager.ContextStack)-1]
|
return gui.State.ContextManager.ContextStack[len(gui.State.ContextManager.ContextStack)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) currentSideContext() *ListContext {
|
// the status panel is not yet a list context (and may never be), so this method is not
|
||||||
|
// quite the same as currentSideContext()
|
||||||
|
func (gui *Gui) currentSideListContext() *ListContext {
|
||||||
|
context := gui.currentSideContext()
|
||||||
|
listContext, ok := context.(*ListContext)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return listContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) currentSideContext() Context {
|
||||||
gui.State.ContextManager.Lock()
|
gui.State.ContextManager.Lock()
|
||||||
defer gui.State.ContextManager.Unlock()
|
defer gui.State.ContextManager.Unlock()
|
||||||
|
|
||||||
@ -583,7 +596,7 @@ func (gui *Gui) currentSideContext() *ListContext {
|
|||||||
|
|
||||||
// on startup the stack can be empty so we'll return an empty string in that case
|
// on startup the stack can be empty so we'll return an empty string in that case
|
||||||
if len(stack) == 0 {
|
if len(stack) == 0 {
|
||||||
return nil
|
return gui.defaultSideContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the first context in the stack with the type of SIDE_CONTEXT
|
// find the first context in the stack with the type of SIDE_CONTEXT
|
||||||
@ -591,20 +604,19 @@ func (gui *Gui) currentSideContext() *ListContext {
|
|||||||
context := stack[len(stack)-1-i]
|
context := stack[len(stack)-1-i]
|
||||||
|
|
||||||
if context.GetKind() == SIDE_CONTEXT {
|
if context.GetKind() == SIDE_CONTEXT {
|
||||||
// not all side contexts are list contexts (e.g. the status panel)
|
return context
|
||||||
listContext, ok := context.(*ListContext)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return listContext
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return gui.defaultSideContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) defaultSideContext() Context {
|
func (gui *Gui) defaultSideContext() Context {
|
||||||
return gui.State.Contexts.Files
|
if gui.State.Modes.Filtering.Active() {
|
||||||
|
return gui.State.Contexts.BranchCommits
|
||||||
|
} else {
|
||||||
|
return gui.State.Contexts.Files
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the need to do this: always use a mapping
|
// remove the need to do this: always use a mapping
|
||||||
@ -618,7 +630,7 @@ func (gui *Gui) setInitialViewContexts() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
view.Context = context.GetKey()
|
view.Context = string(context.GetKey())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,15 +690,15 @@ func (gui *Gui) onViewFocusLost(v *gocui.View, newView *gocui.View) error {
|
|||||||
// which currently just means a context that affects both the main and secondary views
|
// which currently just means a context that affects both the main and secondary views
|
||||||
// other views can have their context changed directly but this function helps
|
// other views can have their context changed directly but this function helps
|
||||||
// keep the main and secondary views in sync
|
// keep the main and secondary views in sync
|
||||||
func (gui *Gui) changeMainViewsContext(contextKey string) {
|
func (gui *Gui) changeMainViewsContext(contextKey ContextKey) {
|
||||||
if gui.State.MainContext == contextKey {
|
if gui.State.MainContext == contextKey {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch contextKey {
|
switch contextKey {
|
||||||
case MAIN_NORMAL_CONTEXT_KEY, MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY, MAIN_MERGING_CONTEXT_KEY:
|
case MAIN_NORMAL_CONTEXT_KEY, MAIN_PATCH_BUILDING_CONTEXT_KEY, MAIN_STAGING_CONTEXT_KEY, MAIN_MERGING_CONTEXT_KEY:
|
||||||
gui.getMainView().Context = contextKey
|
gui.Views.Main.Context = string(contextKey)
|
||||||
gui.getSecondaryView().Context = contextKey
|
gui.Views.Secondary.Context = string(contextKey)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unknown context for main: %s", contextKey))
|
panic(fmt.Sprintf("unknown context for main: %s", contextKey))
|
||||||
}
|
}
|
||||||
@ -737,7 +749,7 @@ type tabContext struct {
|
|||||||
contexts []Context
|
contexts []Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) mustContextForContextKey(contextKey string) Context {
|
func (gui *Gui) mustContextForContextKey(contextKey ContextKey) Context {
|
||||||
context, ok := gui.contextForContextKey(contextKey)
|
context, ok := gui.contextForContextKey(contextKey)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -747,7 +759,7 @@ func (gui *Gui) mustContextForContextKey(contextKey string) Context {
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) contextForContextKey(contextKey string) (Context, bool) {
|
func (gui *Gui) contextForContextKey(contextKey ContextKey) (Context, bool) {
|
||||||
for _, context := range gui.allContexts() {
|
for _, context := range gui.allContexts() {
|
||||||
if context.GetKey() == contextKey {
|
if context.GetKey() == contextKey {
|
||||||
return context, true
|
return context, true
|
||||||
@ -763,7 +775,7 @@ func (gui *Gui) rerenderView(viewName string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
contextKey := v.Context
|
contextKey := ContextKey(v.Context)
|
||||||
context := gui.mustContextForContextKey(contextKey)
|
context := gui.mustContextForContextKey(contextKey)
|
||||||
|
|
||||||
return context.HandleRender()
|
return context.HandleRender()
|
||||||
@ -782,7 +794,7 @@ func (gui *Gui) rerenderView(viewName string) error {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
func (gui *Gui) getSideContextSelectedItemId() string {
|
func (gui *Gui) getSideContextSelectedItemId() string {
|
||||||
currentSideContext := gui.currentSideContext()
|
currentSideContext := gui.currentSideListContext()
|
||||||
if currentSideContext == nil {
|
if currentSideContext == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (gui *Gui) promptUserForCredential(passOrUname string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleSubmitCredential() error {
|
func (gui *Gui) handleSubmitCredential() error {
|
||||||
credentialsView := gui.getCredentialsView()
|
credentialsView := gui.Views.Credentials
|
||||||
message := gui.trimmedContent(credentialsView)
|
message := gui.trimmedContent(credentialsView)
|
||||||
gui.credentials <- message
|
gui.credentials <- message
|
||||||
gui.clearEditorView(credentialsView)
|
gui.clearEditorView(credentialsView)
|
||||||
|
@ -176,9 +176,14 @@ func (gui *Gui) GetCustomCommandKeybindings() []*Binding {
|
|||||||
case "":
|
case "":
|
||||||
log.Fatalf("Error parsing custom command keybindings: context not provided (use context: 'global' for the global context). Key: %s, Command: %s", customCommand.Key, customCommand.Command)
|
log.Fatalf("Error parsing custom command keybindings: context not provided (use context: 'global' for the global context). Key: %s, Command: %s", customCommand.Key, customCommand.Command)
|
||||||
default:
|
default:
|
||||||
context, ok := gui.contextForContextKey(customCommand.Context)
|
context, ok := gui.contextForContextKey(ContextKey(customCommand.Context))
|
||||||
|
// stupid golang making me build an array of strings for this.
|
||||||
|
allContextKeyStrings := make([]string, len(allContextKeys))
|
||||||
|
for i := range allContextKeys {
|
||||||
|
allContextKeyStrings[i] = string(allContextKeys[i])
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatalf("Error when setting custom command keybindings: unknown context: %s. Key: %s, Command: %s.\nPermitted contexts: %s", customCommand.Context, customCommand.Key, customCommand.Command, strings.Join(allContextKeys, ", "))
|
log.Fatalf("Error when setting custom command keybindings: unknown context: %s. Key: %s, Command: %s.\nPermitted contexts: %s", customCommand.Context, customCommand.Key, customCommand.Command, strings.Join(allContextKeyStrings, ", "))
|
||||||
}
|
}
|
||||||
// here we assume that a given context will always belong to the same view.
|
// here we assume that a given context will always belong to the same view.
|
||||||
// Currently this is a safe bet but it's by no means guaranteed in the long term
|
// Currently this is a safe bet but it's by no means guaranteed in the long term
|
||||||
|
@ -14,7 +14,7 @@ func (gui *Gui) renderDiff() error {
|
|||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
fmt.Sprintf("git diff --submodule --no-ext-diff --color %s", gui.diffStr()),
|
fmt.Sprintf("git diff --submodule --no-ext-diff --color %s", gui.diffStr()),
|
||||||
)
|
)
|
||||||
task := gui.createRunPtyTask(cmd)
|
task := NewRunPtyTask(cmd)
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
@ -49,7 +49,7 @@ func (gui *Gui) currentDiffTerminals() []string {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
context := gui.currentSideContext()
|
context := gui.currentSideListContext()
|
||||||
if context == nil {
|
if context == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ func (gui *Gui) getSelectedPath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) selectFile(alreadySelected bool) error {
|
func (gui *Gui) selectFile(alreadySelected bool) error {
|
||||||
gui.getFilesView().FocusPoint(0, gui.State.Panels.Files.SelectedLineIdx)
|
gui.Views.Files.FocusPoint(0, gui.State.Panels.Files.SelectedLineIdx)
|
||||||
|
|
||||||
node := gui.getSelectedFileNode()
|
node := gui.getSelectedFileNode()
|
||||||
|
|
||||||
@ -50,17 +50,17 @@ func (gui *Gui) selectFile(alreadySelected bool) error {
|
|||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
title: "",
|
title: "",
|
||||||
task: gui.createRenderStringTask(gui.Tr.NoChangedFiles),
|
task: NewRenderStringTask(gui.Tr.NoChangedFiles),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if !alreadySelected {
|
if !alreadySelected {
|
||||||
// TODO: pull into update task interface
|
// TODO: pull into update task interface
|
||||||
if err := gui.resetOrigin(gui.getMainView()); err != nil {
|
if err := gui.resetOrigin(gui.Views.Main); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := gui.resetOrigin(gui.getSecondaryView()); err != nil {
|
if err := gui.resetOrigin(gui.Views.Secondary); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gui.takeOverMergeConflictScrolling()
|
gui.takeOverMergeConflictScrolling()
|
||||||
@ -75,7 +75,7 @@ func (gui *Gui) selectFile(alreadySelected bool) error {
|
|||||||
|
|
||||||
refreshOpts := refreshMainOpts{main: &viewUpdateOpts{
|
refreshOpts := refreshMainOpts{main: &viewUpdateOpts{
|
||||||
title: gui.Tr.UnstagedChanges,
|
title: gui.Tr.UnstagedChanges,
|
||||||
task: gui.createRunPtyTask(cmd),
|
task: NewRunPtyTask(cmd),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
if node.GetHasUnstagedChanges() {
|
if node.GetHasUnstagedChanges() {
|
||||||
@ -85,7 +85,7 @@ func (gui *Gui) selectFile(alreadySelected bool) error {
|
|||||||
|
|
||||||
refreshOpts.secondary = &viewUpdateOpts{
|
refreshOpts.secondary = &viewUpdateOpts{
|
||||||
title: gui.Tr.StagedChanges,
|
title: gui.Tr.StagedChanges,
|
||||||
task: gui.createRunPtyTask(cmd),
|
task: NewRunPtyTask(cmd),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -105,11 +105,6 @@ func (gui *Gui) refreshFilesAndSubmodules() error {
|
|||||||
|
|
||||||
selectedPath := gui.getSelectedPath()
|
selectedPath := gui.getSelectedPath()
|
||||||
|
|
||||||
filesView := gui.getFilesView()
|
|
||||||
if filesView == nil {
|
|
||||||
// if the filesView hasn't been instantiated yet we just return
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := gui.refreshStateSubmoduleConfigs(); err != nil {
|
if err := gui.refreshStateSubmoduleConfigs(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -122,14 +117,14 @@ func (gui *Gui) refreshFilesAndSubmodules() error {
|
|||||||
gui.Log.Error(err)
|
gui.Log.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.getFilesView().Context == FILES_CONTEXT_KEY {
|
if gui.Views.Files.Context == FILES_CONTEXT_KEY {
|
||||||
// doing this a little custom (as opposed to using gui.postRefreshUpdate) because we handle selecting the file explicitly below
|
// doing this a little custom (as opposed to using gui.postRefreshUpdate) because we handle selecting the file explicitly below
|
||||||
if err := gui.State.Contexts.Files.HandleRender(); err != nil {
|
if err := gui.State.Contexts.Files.HandleRender(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.currentContext().GetKey() == FILES_CONTEXT_KEY || (g.CurrentView() == gui.getMainView() && g.CurrentView().Context == MAIN_MERGING_CONTEXT_KEY) {
|
if gui.currentContext().GetKey() == FILES_CONTEXT_KEY || (g.CurrentView() == gui.Views.Main && g.CurrentView().Context == MAIN_MERGING_CONTEXT_KEY) {
|
||||||
newSelectedPath := gui.getSelectedPath()
|
newSelectedPath := gui.getSelectedPath()
|
||||||
alreadySelected := selectedPath != "" && newSelectedPath == selectedPath
|
alreadySelected := selectedPath != "" && newSelectedPath == selectedPath
|
||||||
if err := gui.selectFile(alreadySelected); err != nil {
|
if err := gui.selectFile(alreadySelected); err != nil {
|
||||||
@ -350,7 +345,7 @@ func (gui *Gui) handleWIPCommitPress() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = gui.renderStringSync("commitMessage", skipHookPreifx)
|
_ = gui.renderStringSync("commitMessage", skipHookPreifx)
|
||||||
if err := gui.getCommitMessageView().SetCursor(len(skipHookPreifx), 0); err != nil {
|
if err := gui.Views.CommitMessage.SetCursor(len(skipHookPreifx), 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +384,6 @@ func (gui *Gui) handleCommitPress() error {
|
|||||||
return gui.promptToStageAllAndRetry(gui.handleCommitPress)
|
return gui.promptToStageAllAndRetry(gui.handleCommitPress)
|
||||||
}
|
}
|
||||||
|
|
||||||
commitMessageView := gui.getCommitMessageView()
|
|
||||||
commitPrefixConfig := gui.commitPrefixConfigForRepo()
|
commitPrefixConfig := gui.commitPrefixConfigForRepo()
|
||||||
if commitPrefixConfig != nil {
|
if commitPrefixConfig != nil {
|
||||||
prefixPattern := commitPrefixConfig.Pattern
|
prefixPattern := commitPrefixConfig.Pattern
|
||||||
@ -400,7 +394,7 @@ func (gui *Gui) handleCommitPress() error {
|
|||||||
}
|
}
|
||||||
prefix := rgx.ReplaceAllString(gui.getCheckedOutBranch().Name, prefixReplace)
|
prefix := rgx.ReplaceAllString(gui.getCheckedOutBranch().Name, prefixReplace)
|
||||||
gui.renderString("commitMessage", prefix)
|
gui.renderString("commitMessage", prefix)
|
||||||
if err := commitMessageView.SetCursor(len(prefix), 0); err != nil {
|
if err := gui.Views.CommitMessage.SetCursor(len(prefix), 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -862,7 +856,7 @@ func (gui *Gui) handleToggleFileTreeView() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.getFilesView().Context == FILES_CONTEXT_KEY {
|
if gui.Views.Files.Context == FILES_CONTEXT_KEY {
|
||||||
if err := gui.State.Contexts.Files.HandleRender(); err != nil {
|
if err := gui.State.Contexts.Files.HandleRender(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
@ -59,30 +60,22 @@ func (gui *Gui) prevScreenMode() error {
|
|||||||
return gui.rerenderViewsWithScreenModeDependentContent()
|
return gui.rerenderViewsWithScreenModeDependentContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollUpView(viewName string) error {
|
func (gui *Gui) scrollUpView(view *gocui.View) error {
|
||||||
mainView, err := gui.g.View(viewName)
|
ox, oy := view.Origin()
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ox, oy := mainView.Origin()
|
|
||||||
newOy := int(math.Max(0, float64(oy-gui.Config.GetUserConfig().Gui.ScrollHeight)))
|
newOy := int(math.Max(0, float64(oy-gui.Config.GetUserConfig().Gui.ScrollHeight)))
|
||||||
return mainView.SetOrigin(ox, newOy)
|
return view.SetOrigin(ox, newOy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollDownView(viewName string) error {
|
func (gui *Gui) scrollDownView(view *gocui.View) error {
|
||||||
mainView, err := gui.g.View(viewName)
|
ox, oy := view.Origin()
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ox, oy := mainView.Origin()
|
|
||||||
y := oy
|
y := oy
|
||||||
canScrollPastBottom := gui.Config.GetUserConfig().Gui.ScrollPastBottom
|
canScrollPastBottom := gui.Config.GetUserConfig().Gui.ScrollPastBottom
|
||||||
if !canScrollPastBottom {
|
if !canScrollPastBottom {
|
||||||
_, sy := mainView.Size()
|
_, sy := view.Size()
|
||||||
y += sy
|
y += sy
|
||||||
}
|
}
|
||||||
scrollHeight := gui.Config.GetUserConfig().Gui.ScrollHeight
|
scrollHeight := gui.Config.GetUserConfig().Gui.ScrollHeight
|
||||||
scrollableLines := mainView.ViewLinesHeight() - y
|
scrollableLines := view.ViewLinesHeight() - y
|
||||||
if scrollableLines > 0 {
|
if scrollableLines > 0 {
|
||||||
// margin is about how many lines must still appear if you scroll
|
// margin is about how many lines must still appear if you scroll
|
||||||
// all the way down. In practice every file ends in a newline so it will really
|
// all the way down. In practice every file ends in a newline so it will really
|
||||||
@ -95,12 +88,12 @@ func (gui *Gui) scrollDownView(viewName string) error {
|
|||||||
scrollHeight = scrollableLines - margin
|
scrollHeight = scrollableLines - margin
|
||||||
}
|
}
|
||||||
if oy+scrollHeight >= 0 {
|
if oy+scrollHeight >= 0 {
|
||||||
if err := mainView.SetOrigin(ox, oy+scrollHeight); err != nil {
|
if err := view.SetOrigin(ox, oy+scrollHeight); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if manager, ok := gui.viewBufferManagerMap[viewName]; ok {
|
if manager, ok := gui.viewBufferManagerMap[view.Name()]; ok {
|
||||||
manager.ReadLines(scrollHeight)
|
manager.ReadLines(scrollHeight)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -111,7 +104,7 @@ func (gui *Gui) scrollUpMain() error {
|
|||||||
gui.State.Panels.Merging.UserScrolling = true
|
gui.State.Panels.Merging.UserScrolling = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.scrollUpView("main")
|
return gui.scrollUpView(gui.Views.Main)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollDownMain() error {
|
func (gui *Gui) scrollDownMain() error {
|
||||||
@ -119,33 +112,31 @@ func (gui *Gui) scrollDownMain() error {
|
|||||||
gui.State.Panels.Merging.UserScrolling = true
|
gui.State.Panels.Merging.UserScrolling = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.scrollDownView("main")
|
return gui.scrollDownView(gui.Views.Main)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollUpSecondary() error {
|
func (gui *Gui) scrollUpSecondary() error {
|
||||||
return gui.scrollUpView("secondary")
|
return gui.scrollUpView(gui.Views.Secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollDownSecondary() error {
|
func (gui *Gui) scrollDownSecondary() error {
|
||||||
return gui.scrollDownView("secondary")
|
return gui.scrollDownView(gui.Views.Secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollUpConfirmationPanel() error {
|
func (gui *Gui) scrollUpConfirmationPanel() error {
|
||||||
view := gui.getConfirmationView()
|
if gui.Views.Confirmation.Editable {
|
||||||
if view != nil || view.Editable {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.scrollUpView("confirmation")
|
return gui.scrollUpView(gui.Views.Confirmation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) scrollDownConfirmationPanel() error {
|
func (gui *Gui) scrollDownConfirmationPanel() error {
|
||||||
view := gui.getConfirmationView()
|
if gui.Views.Confirmation.Editable {
|
||||||
if view != nil || view.Editable {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.scrollDownView("confirmation")
|
return gui.scrollDownView(gui.Views.Confirmation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleRefresh() error {
|
func (gui *Gui) handleRefresh() error {
|
||||||
@ -157,16 +148,14 @@ func (gui *Gui) handleMouseDownMain() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
view := gui.getMainView()
|
|
||||||
|
|
||||||
switch gui.g.CurrentView().Name() {
|
switch gui.g.CurrentView().Name() {
|
||||||
case "files":
|
case "files":
|
||||||
// set filename, set primary/secondary selected, set line number, then switch context
|
// set filename, set primary/secondary selected, set line number, then switch context
|
||||||
// I'll need to know it was changed though.
|
// I'll need to know it was changed though.
|
||||||
// Could I pass something along to the context change?
|
// Could I pass something along to the context change?
|
||||||
return gui.enterFile(false, view.SelectedLineIdx())
|
return gui.enterFile(false, gui.Views.Main.SelectedLineIdx())
|
||||||
case "commitFiles":
|
case "commitFiles":
|
||||||
return gui.enterCommitFile(view.SelectedLineIdx())
|
return gui.enterCommitFile(gui.Views.Main.SelectedLineIdx())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -177,11 +166,9 @@ func (gui *Gui) handleMouseDownSecondary() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
view := gui.getSecondaryView()
|
|
||||||
|
|
||||||
switch gui.g.CurrentView().Name() {
|
switch gui.g.CurrentView().Name() {
|
||||||
case "files":
|
case "files":
|
||||||
return gui.enterFile(true, view.SelectedLineIdx())
|
return gui.enterFile(true, gui.Views.Secondary.SelectedLineIdx())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -192,7 +179,7 @@ func (gui *Gui) handleInfoClick() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
view := gui.getInformationView()
|
view := gui.Views.Information
|
||||||
|
|
||||||
cx, _ := view.Cursor()
|
cx, _ := view.Cursor()
|
||||||
width, _ := view.Size()
|
width, _ := view.Size()
|
||||||
|
@ -106,6 +106,8 @@ type Gui struct {
|
|||||||
|
|
||||||
// this tells us whether our views have been initially set up
|
// this tells us whether our views have been initially set up
|
||||||
ViewsSetup bool
|
ViewsSetup bool
|
||||||
|
|
||||||
|
Views Views
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecordedEvent struct {
|
type RecordedEvent struct {
|
||||||
@ -232,6 +234,28 @@ type panelStates struct {
|
|||||||
Suggestions *suggestionsPanelState
|
Suggestions *suggestionsPanelState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Views struct {
|
||||||
|
Status *gocui.View
|
||||||
|
Files *gocui.View
|
||||||
|
Branches *gocui.View
|
||||||
|
Commits *gocui.View
|
||||||
|
Stash *gocui.View
|
||||||
|
Main *gocui.View
|
||||||
|
Secondary *gocui.View
|
||||||
|
Options *gocui.View
|
||||||
|
Confirmation *gocui.View
|
||||||
|
Menu *gocui.View
|
||||||
|
Credentials *gocui.View
|
||||||
|
CommitMessage *gocui.View
|
||||||
|
CommitFiles *gocui.View
|
||||||
|
Information *gocui.View
|
||||||
|
AppStatus *gocui.View
|
||||||
|
Search *gocui.View
|
||||||
|
SearchPrefix *gocui.View
|
||||||
|
Limit *gocui.View
|
||||||
|
Suggestions *gocui.View
|
||||||
|
}
|
||||||
|
|
||||||
type searchingState struct {
|
type searchingState struct {
|
||||||
view *gocui.View
|
view *gocui.View
|
||||||
isSearching bool
|
isSearching bool
|
||||||
@ -260,7 +284,7 @@ type CherryPicking struct {
|
|||||||
CherryPickedCommits []*models.Commit
|
CherryPickedCommits []*models.Commit
|
||||||
|
|
||||||
// we only allow cherry picking from one context at a time, so you can't copy a commit from the local commits context and then also copy a commit in the reflog context
|
// we only allow cherry picking from one context at a time, so you can't copy a commit from the local commits context and then also copy a commit in the reflog context
|
||||||
ContextKey string
|
ContextKey ContextKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CherryPicking) Active() bool {
|
func (m *CherryPicking) Active() bool {
|
||||||
@ -306,8 +330,8 @@ type guiState struct {
|
|||||||
MenuItems []*menuItem
|
MenuItems []*menuItem
|
||||||
Updating bool
|
Updating bool
|
||||||
Panels *panelStates
|
Panels *panelStates
|
||||||
MainContext string // used to keep the main and secondary views' contexts in sync
|
|
||||||
SplitMainPanel bool
|
SplitMainPanel bool
|
||||||
|
MainContext ContextKey // used to keep the main and secondary views' contexts in sync
|
||||||
RetainOriginalDir bool
|
RetainOriginalDir bool
|
||||||
IsRefreshingFiles bool
|
IsRefreshingFiles bool
|
||||||
Searching searchingState
|
Searching searchingState
|
||||||
|
@ -625,21 +625,21 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{TAGS_CONTEXT_KEY},
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
Key: gui.getKey(config.Universal.Select),
|
Key: gui.getKey(config.Universal.Select),
|
||||||
Handler: gui.handleCheckoutTag,
|
Handler: gui.withSelectedTag(gui.handleCheckoutTag),
|
||||||
Description: gui.Tr.LcCheckout,
|
Description: gui.Tr.LcCheckout,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{TAGS_CONTEXT_KEY},
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
Key: gui.getKey(config.Universal.Remove),
|
Key: gui.getKey(config.Universal.Remove),
|
||||||
Handler: gui.handleDeleteTag,
|
Handler: gui.withSelectedTag(gui.handleDeleteTag),
|
||||||
Description: gui.Tr.LcDeleteTag,
|
Description: gui.Tr.LcDeleteTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{TAGS_CONTEXT_KEY},
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
Key: gui.getKey(config.Branches.PushTag),
|
Key: gui.getKey(config.Branches.PushTag),
|
||||||
Handler: gui.handlePushTag,
|
Handler: gui.withSelectedTag(gui.handlePushTag),
|
||||||
Description: gui.Tr.LcPushTag,
|
Description: gui.Tr.LcPushTag,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -653,7 +653,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||||||
ViewName: "branches",
|
ViewName: "branches",
|
||||||
Contexts: []string{TAGS_CONTEXT_KEY},
|
Contexts: []string{TAGS_CONTEXT_KEY},
|
||||||
Key: gui.getKey(config.Commits.ViewResetOptions),
|
Key: gui.getKey(config.Commits.ViewResetOptions),
|
||||||
Handler: gui.handleCreateResetToTagMenu,
|
Handler: gui.withSelectedTag(gui.handleCreateResetToTagMenu),
|
||||||
Description: gui.Tr.LcViewResetOptions,
|
Description: gui.Tr.LcViewResetOptions,
|
||||||
OpensMenu: true,
|
OpensMenu: true,
|
||||||
},
|
},
|
||||||
|
@ -31,29 +31,22 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
|
|
||||||
minimumHeight := 9
|
minimumHeight := 9
|
||||||
minimumWidth := 10
|
minimumWidth := 10
|
||||||
if height < minimumHeight || width < minimumWidth {
|
var err error
|
||||||
v, err := g.SetView("limit", 0, 0, width-1, height-1, 0)
|
gui.Views.Limit, err = g.SetView("limit", 0, 0, width-1, height-1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
v.Title = gui.Tr.NotEnoughSpace
|
|
||||||
v.Wrap = true
|
|
||||||
_, _ = g.SetViewOnTop("limit")
|
|
||||||
}
|
}
|
||||||
return nil
|
gui.Views.Limit.Title = gui.Tr.NotEnoughSpace
|
||||||
|
gui.Views.Limit.Wrap = true
|
||||||
}
|
}
|
||||||
|
gui.Views.Limit.Visible = height < minimumHeight || width < minimumWidth
|
||||||
|
|
||||||
informationStr := gui.informationStr()
|
informationStr := gui.informationStr()
|
||||||
appStatus := gui.statusManager.getStatusString()
|
appStatus := gui.statusManager.getStatusString()
|
||||||
|
|
||||||
viewDimensions := gui.getWindowDimensions(informationStr, appStatus)
|
viewDimensions := gui.getWindowDimensions(informationStr, appStatus)
|
||||||
|
|
||||||
_, _ = g.SetViewOnBottom("limit")
|
|
||||||
_ = g.DeleteView("limit")
|
|
||||||
|
|
||||||
textColor := theme.GocuiDefaultTextColor
|
|
||||||
|
|
||||||
// reading more lines into main view buffers upon resize
|
// reading more lines into main view buffers upon resize
|
||||||
prevMainView, err := gui.g.View("main")
|
prevMainView, err := gui.g.View("main")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -79,17 +72,17 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
// to render content as soon as it appears, because lazyloaded content (via a pty task)
|
// to render content as soon as it appears, because lazyloaded content (via a pty task)
|
||||||
// cares about the size of the view.
|
// cares about the size of the view.
|
||||||
view, err := g.SetView(viewName, 0, 0, width, height, 0)
|
view, err := g.SetView(viewName, 0, 0, width, height, 0)
|
||||||
if err != nil {
|
if view != nil {
|
||||||
return view, err
|
view.Visible = false
|
||||||
}
|
}
|
||||||
return g.SetViewOnBottom(viewName)
|
return view, err
|
||||||
}
|
}
|
||||||
|
|
||||||
frameOffset := 1
|
frameOffset := 1
|
||||||
if frame {
|
if frame {
|
||||||
frameOffset = 0
|
frameOffset = 0
|
||||||
}
|
}
|
||||||
return g.SetView(
|
view, err := g.SetView(
|
||||||
viewName,
|
viewName,
|
||||||
dimensionsObj.X0-frameOffset,
|
dimensionsObj.X0-frameOffset,
|
||||||
dimensionsObj.Y0-frameOffset,
|
dimensionsObj.Y0-frameOffset,
|
||||||
@ -97,172 +90,150 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
dimensionsObj.Y1+frameOffset,
|
dimensionsObj.Y1+frameOffset,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if view != nil {
|
||||||
|
view.Visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return view, err
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := setViewFromDimensions("main", "main", true)
|
gui.Views.Main, err = setViewFromDimensions("main", "main", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.Title = gui.Tr.DiffTitle
|
gui.Views.Main.Title = gui.Tr.DiffTitle
|
||||||
v.Wrap = true
|
gui.Views.Main.Wrap = true
|
||||||
v.FgColor = textColor
|
gui.Views.Main.FgColor = theme.GocuiDefaultTextColor
|
||||||
v.IgnoreCarriageReturns = true
|
gui.Views.Main.IgnoreCarriageReturns = true
|
||||||
}
|
}
|
||||||
|
|
||||||
secondaryView, err := setViewFromDimensions("secondary", "secondary", true)
|
gui.Views.Secondary, err = setViewFromDimensions("secondary", "secondary", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
secondaryView.Title = gui.Tr.DiffTitle
|
gui.Views.Secondary.Title = gui.Tr.DiffTitle
|
||||||
secondaryView.Wrap = true
|
gui.Views.Secondary.Wrap = true
|
||||||
secondaryView.FgColor = textColor
|
gui.Views.Secondary.FgColor = theme.GocuiDefaultTextColor
|
||||||
secondaryView.IgnoreCarriageReturns = true
|
gui.Views.Secondary.IgnoreCarriageReturns = true
|
||||||
}
|
}
|
||||||
|
|
||||||
hiddenViewOffset := 9999
|
if gui.Views.Status, err = setViewFromDimensions("status", "status", true); err != nil {
|
||||||
|
|
||||||
if v, err := setViewFromDimensions("status", "status", true); err != nil {
|
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.Title = gui.Tr.StatusTitle
|
gui.Views.Status.Title = gui.Tr.StatusTitle
|
||||||
v.FgColor = textColor
|
gui.Views.Status.FgColor = theme.GocuiDefaultTextColor
|
||||||
}
|
}
|
||||||
|
|
||||||
filesView, err := setViewFromDimensions("files", "files", true)
|
gui.Views.Files, err = setViewFromDimensions("files", "files", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
filesView.Highlight = true
|
gui.Views.Files.Highlight = true
|
||||||
filesView.Title = gui.Tr.FilesTitle
|
gui.Views.Files.Title = gui.Tr.FilesTitle
|
||||||
filesView.FgColor = textColor
|
gui.Views.Files.FgColor = theme.GocuiDefaultTextColor
|
||||||
filesView.ContainsList = true
|
gui.Views.Files.ContainsList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
branchesView, err := setViewFromDimensions("branches", "branches", true)
|
gui.Views.Branches, err = setViewFromDimensions("branches", "branches", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
branchesView.Title = gui.Tr.BranchesTitle
|
gui.Views.Branches.Title = gui.Tr.BranchesTitle
|
||||||
branchesView.FgColor = textColor
|
gui.Views.Branches.FgColor = theme.GocuiDefaultTextColor
|
||||||
branchesView.ContainsList = true
|
gui.Views.Branches.ContainsList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
commitFilesView, err := setViewFromDimensions("commitFiles", gui.State.Contexts.CommitFiles.GetWindowName(), true)
|
gui.Views.CommitFiles, err = setViewFromDimensions("commitFiles", gui.State.Contexts.CommitFiles.GetWindowName(), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
commitFilesView.Title = gui.Tr.CommitFiles
|
gui.Views.CommitFiles.Title = gui.Tr.CommitFiles
|
||||||
commitFilesView.FgColor = textColor
|
gui.Views.CommitFiles.FgColor = theme.GocuiDefaultTextColor
|
||||||
commitFilesView.ContainsList = true
|
gui.Views.CommitFiles.ContainsList = true
|
||||||
_, _ = gui.g.SetViewOnBottom("commitFiles")
|
|
||||||
}
|
}
|
||||||
|
// if the commit files view is the view to be displayed for its window, we'll display it
|
||||||
|
gui.Views.CommitFiles.Visible = gui.getViewNameForWindow(gui.State.Contexts.CommitFiles.GetWindowName()) == "commitFiles"
|
||||||
|
|
||||||
commitsView, err := setViewFromDimensions("commits", "commits", true)
|
gui.Views.Commits, err = setViewFromDimensions("commits", "commits", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
commitsView.Title = gui.Tr.CommitsTitle
|
gui.Views.Commits.Title = gui.Tr.CommitsTitle
|
||||||
commitsView.FgColor = textColor
|
gui.Views.Commits.FgColor = theme.GocuiDefaultTextColor
|
||||||
commitsView.ContainsList = true
|
gui.Views.Commits.ContainsList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
stashView, err := setViewFromDimensions("stash", "stash", true)
|
gui.Views.Stash, err = setViewFromDimensions("stash", "stash", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stashView.Title = gui.Tr.StashTitle
|
gui.Views.Stash.Title = gui.Tr.StashTitle
|
||||||
stashView.FgColor = textColor
|
gui.Views.Stash.FgColor = theme.GocuiDefaultTextColor
|
||||||
stashView.ContainsList = true
|
gui.Views.Stash.ContainsList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.getCommitMessageView() == nil {
|
if gui.Views.Options, err = setViewFromDimensions("options", "options", false); err != nil {
|
||||||
// doesn't matter where this view starts because it will be hidden
|
|
||||||
if commitMessageView, err := g.SetView("commitMessage", hiddenViewOffset, hiddenViewOffset, hiddenViewOffset+10, hiddenViewOffset+10, 0); err != nil {
|
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, _ = g.SetViewOnBottom("commitMessage")
|
|
||||||
commitMessageView.Title = gui.Tr.CommitMessage
|
|
||||||
commitMessageView.FgColor = textColor
|
|
||||||
commitMessageView.Editable = true
|
|
||||||
commitMessageView.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if check, _ := g.View("credentials"); check == nil {
|
|
||||||
// doesn't matter where this view starts because it will be hidden
|
|
||||||
if credentialsView, err := g.SetView("credentials", hiddenViewOffset, hiddenViewOffset, hiddenViewOffset+10, hiddenViewOffset+10, 0); err != nil {
|
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, _ = g.SetViewOnBottom("credentials")
|
|
||||||
credentialsView.Title = gui.Tr.CredentialsUsername
|
|
||||||
credentialsView.FgColor = textColor
|
|
||||||
credentialsView.Editable = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v, err := setViewFromDimensions("options", "options", false); err != nil {
|
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.Frame = false
|
gui.Views.Options.Frame = false
|
||||||
v.FgColor = theme.OptionsColor
|
gui.Views.Options.FgColor = theme.OptionsColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// this view takes up one character. Its only purpose is to show the slash when searching
|
// this view takes up one character. Its only purpose is to show the slash when searching
|
||||||
if searchPrefixView, err := setViewFromDimensions("searchPrefix", "searchPrefix", false); err != nil {
|
if gui.Views.SearchPrefix, err = setViewFromDimensions("searchPrefix", "searchPrefix", false); err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
searchPrefixView.BgColor = gocui.ColorDefault
|
gui.Views.SearchPrefix.BgColor = gocui.ColorDefault
|
||||||
searchPrefixView.FgColor = gocui.ColorGreen
|
gui.Views.SearchPrefix.FgColor = gocui.ColorGreen
|
||||||
searchPrefixView.Frame = false
|
gui.Views.SearchPrefix.Frame = false
|
||||||
gui.setViewContent(searchPrefixView, SEARCH_PREFIX)
|
gui.setViewContent(gui.Views.SearchPrefix, SEARCH_PREFIX)
|
||||||
}
|
}
|
||||||
|
|
||||||
if searchView, err := setViewFromDimensions("search", "search", false); err != nil {
|
if gui.Views.Search, err = setViewFromDimensions("search", "search", false); err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
searchView.BgColor = gocui.ColorDefault
|
gui.Views.Search.BgColor = gocui.ColorDefault
|
||||||
searchView.FgColor = gocui.ColorGreen
|
gui.Views.Search.FgColor = gocui.ColorGreen
|
||||||
searchView.Frame = false
|
gui.Views.Search.Frame = false
|
||||||
searchView.Editable = true
|
gui.Views.Search.Editable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if appStatusView, err := setViewFromDimensions("appStatus", "appStatus", false); err != nil {
|
if gui.Views.AppStatus, err = setViewFromDimensions("appStatus", "appStatus", false); err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
appStatusView.BgColor = gocui.ColorDefault
|
gui.Views.AppStatus.BgColor = gocui.ColorDefault
|
||||||
appStatusView.FgColor = gocui.ColorCyan
|
gui.Views.AppStatus.FgColor = gocui.ColorCyan
|
||||||
appStatusView.Frame = false
|
gui.Views.AppStatus.Frame = false
|
||||||
_, _ = g.SetViewOnBottom("appStatus")
|
gui.Views.AppStatus.Visible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
informationView, err := setViewFromDimensions("information", "information", false)
|
gui.Views.Information, err = setViewFromDimensions("information", "information", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
informationView.BgColor = gocui.ColorDefault
|
gui.Views.Information.BgColor = gocui.ColorDefault
|
||||||
informationView.FgColor = gocui.ColorGreen
|
gui.Views.Information.FgColor = gocui.ColorGreen
|
||||||
informationView.Frame = false
|
gui.Views.Information.Frame = false
|
||||||
gui.renderString("information", INFO_SECTION_PADDING+informationStr)
|
gui.renderString("information", INFO_SECTION_PADDING+informationStr)
|
||||||
}
|
}
|
||||||
if gui.State.OldInformation != informationStr {
|
if gui.State.OldInformation != informationStr {
|
||||||
gui.setViewContent(informationView, informationStr)
|
gui.setViewContent(gui.Views.Information, informationStr)
|
||||||
gui.State.OldInformation = informationStr
|
gui.State.OldInformation = informationStr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +260,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore contexts whose view is owned by another context right now
|
// ignore contexts whose view is owned by another context right now
|
||||||
if view.Context != listContext.GetKey() {
|
if ContextKey(view.Context) != listContext.GetKey() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,9 +273,9 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
view.SetOnSelectItem(gui.onSelectItemWrapper(listContext.onSearchSelect))
|
view.SetOnSelectItem(gui.onSelectItemWrapper(listContext.onSearchSelect))
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.getMainView().SetOnSelectItem(gui.onSelectItemWrapper(gui.handlelineByLineNavigateTo))
|
gui.Views.Main.SetOnSelectItem(gui.onSelectItemWrapper(gui.handlelineByLineNavigateTo))
|
||||||
|
|
||||||
mainViewWidth, mainViewHeight := gui.getMainView().Size()
|
mainViewWidth, mainViewHeight := gui.Views.Main.Size()
|
||||||
if mainViewWidth != gui.State.PrevMainWidth || mainViewHeight != gui.State.PrevMainHeight {
|
if mainViewWidth != gui.State.PrevMainWidth || mainViewHeight != gui.State.PrevMainHeight {
|
||||||
gui.State.PrevMainWidth = mainViewWidth
|
gui.State.PrevMainWidth = mainViewWidth
|
||||||
gui.State.PrevMainHeight = mainViewHeight
|
gui.State.PrevMainHeight = mainViewHeight
|
||||||
@ -320,28 +291,24 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
return gui.resizeCurrentPopupPanel()
|
return gui.resizeCurrentPopupPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) setHiddenView(viewName string) (*gocui.View, error) {
|
||||||
|
// arbitrarily giving the view enough size so that we don't get an error, but
|
||||||
|
// it's expected that the view will be given the correct size before being shown
|
||||||
|
return gui.g.SetView(viewName, 0, 0, 10, 10, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *Gui) onInitialViewsCreationForRepo() error {
|
func (gui *Gui) onInitialViewsCreationForRepo() error {
|
||||||
gui.setInitialViewContexts()
|
gui.setInitialViewContexts()
|
||||||
|
|
||||||
// hide any popup views. This only applies when we've just switched repos
|
// hide any popup views. This only applies when we've just switched repos
|
||||||
for _, viewName := range gui.popupViewNames() {
|
for _, viewName := range gui.popupViewNames() {
|
||||||
_, _ = gui.g.SetViewOnBottom(viewName)
|
view, err := gui.g.View(viewName)
|
||||||
}
|
if err == nil {
|
||||||
|
view.Visible = false
|
||||||
// the status panel is not actually a list context at the moment, so it is excluded
|
|
||||||
// here. Arguably that's quite convenient because it means we're back to starting
|
|
||||||
// in the files panel when landing in a new repo, but when returning from a submodule
|
|
||||||
// we'll be back in the submodules context. This still seems awkward though, and it's
|
|
||||||
// definitely going to break when (if) we make the status context a list context
|
|
||||||
initialContext := gui.currentSideContext()
|
|
||||||
if initialContext == nil {
|
|
||||||
if gui.State.Modes.Filtering.Active() {
|
|
||||||
initialContext = gui.State.Contexts.BranchCommits
|
|
||||||
} else {
|
|
||||||
initialContext = gui.State.Contexts.Files
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialContext := gui.currentSideContext()
|
||||||
if err := gui.pushContext(initialContext); err != nil {
|
if err := gui.pushContext(initialContext); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -350,6 +317,49 @@ func (gui *Gui) onInitialViewsCreationForRepo() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) onInitialViewsCreation() error {
|
func (gui *Gui) onInitialViewsCreation() error {
|
||||||
|
// creating some views which are hidden at the start but we need to exist so that we can set an initial ordering
|
||||||
|
if err := gui.createHiddenViews(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we order the views (in order of bottom first)
|
||||||
|
layerOneViews := []*gocui.View{
|
||||||
|
// first layer. Ordering within this layer does not matter because there are
|
||||||
|
// no overlapping views
|
||||||
|
gui.Views.Status,
|
||||||
|
gui.Views.Files,
|
||||||
|
gui.Views.Branches,
|
||||||
|
gui.Views.Commits,
|
||||||
|
gui.Views.Stash,
|
||||||
|
gui.Views.CommitFiles,
|
||||||
|
gui.Views.Main,
|
||||||
|
gui.Views.Secondary,
|
||||||
|
|
||||||
|
// bottom line
|
||||||
|
gui.Views.Options,
|
||||||
|
gui.Views.AppStatus,
|
||||||
|
gui.Views.Information,
|
||||||
|
gui.Views.Search,
|
||||||
|
gui.Views.SearchPrefix,
|
||||||
|
|
||||||
|
// popups. Ordering within this layer does not matter because there should
|
||||||
|
// only be one popup shown at a time
|
||||||
|
gui.Views.CommitMessage,
|
||||||
|
gui.Views.Credentials,
|
||||||
|
gui.Views.Menu,
|
||||||
|
gui.Views.Confirmation,
|
||||||
|
gui.Views.Suggestions,
|
||||||
|
|
||||||
|
// this guy will cover everything else when it appears
|
||||||
|
gui.Views.Limit,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, view := range layerOneViews {
|
||||||
|
if _, err := gui.g.SetViewOnTop(view.Name()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gui.g.Mutexes.ViewsMutex.Lock()
|
gui.g.Mutexes.ViewsMutex.Lock()
|
||||||
// add tabs to views
|
// add tabs to views
|
||||||
for _, view := range gui.g.Views() {
|
for _, view := range gui.g.Views() {
|
||||||
@ -378,3 +388,58 @@ func (gui *Gui) onInitialViewsCreation() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) createHiddenViews() error {
|
||||||
|
// doesn't matter where this view starts because it will be hidden
|
||||||
|
var err error
|
||||||
|
if gui.Views.CommitMessage, err = gui.setHiddenView("commitMessage"); err != nil {
|
||||||
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gui.Views.CommitMessage.Visible = false
|
||||||
|
gui.Views.CommitMessage.Title = gui.Tr.CommitMessage
|
||||||
|
gui.Views.CommitMessage.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
gui.Views.CommitMessage.Editable = true
|
||||||
|
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
||||||
|
}
|
||||||
|
|
||||||
|
// doesn't matter where this view starts because it will be hidden
|
||||||
|
if gui.Views.Credentials, err = gui.setHiddenView("credentials"); err != nil {
|
||||||
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gui.Views.Credentials.Visible = false
|
||||||
|
gui.Views.Credentials.Title = gui.Tr.CredentialsUsername
|
||||||
|
gui.Views.Credentials.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
gui.Views.Credentials.Editable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// not worrying about setting attributes because that will be done when the view is actually shown
|
||||||
|
gui.Views.Confirmation, err = gui.setHiddenView("confirmation")
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gui.Views.Confirmation.Visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// not worrying about setting attributes because that will be done when the view is actually shown
|
||||||
|
gui.Views.Suggestions, err = gui.setHiddenView("suggestions")
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gui.Views.Suggestions.Visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// not worrying about setting attributes because that will be done when the view is actually shown
|
||||||
|
gui.Views.Menu, err = gui.setHiddenView("menu")
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() != UNKNOWN_VIEW_ERROR_MSG {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gui.Views.Menu.Visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -82,9 +82,8 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secondaryView := gui.getSecondaryView()
|
gui.Views.Secondary.Highlight = true
|
||||||
secondaryView.Highlight = true
|
gui.Views.Secondary.Wrap = false
|
||||||
secondaryView.Wrap = false
|
|
||||||
|
|
||||||
secondaryPatchParser, err := patch.NewPatchParser(gui.Log, secondaryDiff)
|
secondaryPatchParser, err := patch.NewPatchParser(gui.Log, secondaryDiff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +91,7 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
|
|||||||
}
|
}
|
||||||
|
|
||||||
gui.g.Update(func(*gocui.Gui) error {
|
gui.g.Update(func(*gocui.Gui) error {
|
||||||
gui.setViewContent(gui.getSecondaryView(), secondaryPatchParser.Render(-1, -1, nil))
|
gui.setViewContent(gui.Views.Secondary, secondaryPatchParser.Render(-1, -1, nil))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -184,7 +183,7 @@ func (gui *Gui) handleLBLMouseDown() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
newSelectedLineIdx := gui.getMainView().SelectedLineIdx()
|
newSelectedLineIdx := gui.Views.Main.SelectedLineIdx()
|
||||||
state.FirstLineIdx = newSelectedLineIdx
|
state.FirstLineIdx = newSelectedLineIdx
|
||||||
state.LastLineIdx = newSelectedLineIdx
|
state.LastLineIdx = newSelectedLineIdx
|
||||||
|
|
||||||
@ -200,7 +199,7 @@ func (gui *Gui) handleMouseDrag() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.LBLSelectLine(gui.getMainView().SelectedLineIdx(), state)
|
return gui.LBLSelectLine(gui.Views.Main.SelectedLineIdx(), state)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,12 +247,11 @@ func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
|
|||||||
}
|
}
|
||||||
colorDiff := state.PatchParser.Render(state.FirstLineIdx, state.LastLineIdx, includedLineIndices)
|
colorDiff := state.PatchParser.Render(state.FirstLineIdx, state.LastLineIdx, includedLineIndices)
|
||||||
|
|
||||||
mainView := gui.getMainView()
|
gui.Views.Main.Highlight = true
|
||||||
mainView.Highlight = true
|
gui.Views.Main.Wrap = false
|
||||||
mainView.Wrap = false
|
|
||||||
|
|
||||||
gui.g.Update(func(*gocui.Gui) error {
|
gui.g.Update(func(*gocui.Gui) error {
|
||||||
gui.setViewContent(gui.getMainView(), colorDiff)
|
gui.setViewContent(gui.Views.Main, colorDiff)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -263,7 +261,7 @@ func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
|
|||||||
// focusSelection works out the best focus for the staging panel given the
|
// focusSelection works out the best focus for the staging panel given the
|
||||||
// selected line and size of the hunk
|
// selected line and size of the hunk
|
||||||
func (gui *Gui) focusSelection(includeCurrentHunk bool, state *lBlPanelState) error {
|
func (gui *Gui) focusSelection(includeCurrentHunk bool, state *lBlPanelState) error {
|
||||||
stagingView := gui.getMainView()
|
stagingView := gui.Views.Main
|
||||||
|
|
||||||
_, viewHeight := stagingView.Size()
|
_, viewHeight := stagingView.Size()
|
||||||
bufferHeight := viewHeight - 1
|
bufferHeight := viewHeight - 1
|
||||||
@ -367,7 +365,7 @@ func (gui *Gui) handleOpenFileAtLine() error {
|
|||||||
|
|
||||||
func (gui *Gui) handleLineByLineNextPage() error {
|
func (gui *Gui) handleLineByLineNextPage() error {
|
||||||
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
||||||
newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.getMainView())
|
newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.Views.Main)
|
||||||
|
|
||||||
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
|
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
|
||||||
})
|
})
|
||||||
@ -375,7 +373,7 @@ func (gui *Gui) handleLineByLineNextPage() error {
|
|||||||
|
|
||||||
func (gui *Gui) handleLineByLinePrevPage() error {
|
func (gui *Gui) handleLineByLinePrevPage() error {
|
||||||
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
||||||
newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.getMainView())
|
newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.Views.Main)
|
||||||
|
|
||||||
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
|
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
|
||||||
})
|
})
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type ListContext struct {
|
type ListContext struct {
|
||||||
ViewName string
|
ViewName string
|
||||||
ContextKey string
|
ContextKey ContextKey
|
||||||
GetItemsLength func() int
|
GetItemsLength func() int
|
||||||
GetDisplayStrings func() [][]string
|
GetDisplayStrings func() [][]string
|
||||||
OnFocus func() error
|
OnFocus func() error
|
||||||
@ -103,7 +103,7 @@ func (lc *ListContext) OnRender() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *ListContext) GetKey() string {
|
func (lc *ListContext) GetKey() ContextKey {
|
||||||
return lc.ContextKey
|
return lc.ContextKey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +136,10 @@ func (lc *ListContext) HandleFocus() error {
|
|||||||
view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx())
|
view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx())
|
||||||
|
|
||||||
if lc.ResetMainViewOriginOnFocus {
|
if lc.ResetMainViewOriginOnFocus {
|
||||||
if err := lc.Gui.resetOrigin(lc.Gui.getMainView()); err != nil {
|
if err := lc.Gui.resetOrigin(lc.Gui.Views.Main); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := lc.Gui.resetOrigin(lc.Gui.getSecondaryView()); err != nil {
|
if err := lc.Gui.resetOrigin(lc.Gui.Views.Secondary); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ func (gui *Gui) menuListContext() *ListContext {
|
|||||||
return &ListContext{
|
return &ListContext{
|
||||||
ViewName: "menu",
|
ViewName: "menu",
|
||||||
ContextKey: "menu",
|
ContextKey: "menu",
|
||||||
GetItemsLength: func() int { return gui.getMenuView().LinesHeight() },
|
GetItemsLength: func() int { return gui.Views.Menu.LinesHeight() },
|
||||||
GetPanelState: func() IListPanelState { return gui.State.Panels.Menu },
|
GetPanelState: func() IListPanelState { return gui.State.Panels.Menu },
|
||||||
OnFocus: gui.handleMenuSelect,
|
OnFocus: gui.handleMenuSelect,
|
||||||
OnClickSelectedItem: gui.onMenuPress,
|
OnClickSelectedItem: gui.onMenuPress,
|
||||||
@ -556,16 +556,16 @@ func (gui *Gui) getListContextKeyBindings() []*Binding {
|
|||||||
listContext := listContext
|
listContext := listContext
|
||||||
|
|
||||||
bindings = append(bindings, []*Binding{
|
bindings = append(bindings, []*Binding{
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.PrevItemAlt), Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.PrevItemAlt), Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.PrevItem), Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.PrevItem), Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, Handler: listContext.handlePrevLine},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.NextItemAlt), Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.NextItemAlt), Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.NextItem), Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.NextItem), Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.PrevPage), Modifier: gocui.ModNone, Handler: listContext.handlePrevPage, Description: gui.Tr.LcPrevPage},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.PrevPage), Modifier: gocui.ModNone, Handler: listContext.handlePrevPage, Description: gui.Tr.LcPrevPage},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.NextPage), Modifier: gocui.ModNone, Handler: listContext.handleNextPage, Description: gui.Tr.LcNextPage},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.NextPage), Modifier: gocui.ModNone, Handler: listContext.handleNextPage, Description: gui.Tr.LcNextPage},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gui.getKey(keybindingConfig.Universal.GotoTop), Modifier: gocui.ModNone, Handler: listContext.handleGotoTop, Description: gui.Tr.LcGotoTop},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gui.getKey(keybindingConfig.Universal.GotoTop), Modifier: gocui.ModNone, Handler: listContext.handleGotoTop, Description: gui.Tr.LcGotoTop},
|
||||||
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{listContext.ContextKey}, Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
{ViewName: listContext.ViewName, Tag: "navigation", Contexts: []string{string(listContext.ContextKey)}, Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: listContext.handleNextLine},
|
||||||
{ViewName: listContext.ViewName, Contexts: []string{listContext.ContextKey}, Key: gocui.MouseLeft, Modifier: gocui.ModNone, Handler: listContext.handleClick},
|
{ViewName: listContext.ViewName, Contexts: []string{string(listContext.ContextKey)}, Key: gocui.MouseLeft, Modifier: gocui.ModNone, Handler: listContext.handleClick},
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
// the commits panel needs to lazyload things so it has a couple of its own handlers
|
// the commits panel needs to lazyload things so it has a couple of its own handlers
|
||||||
@ -579,7 +579,7 @@ func (gui *Gui) getListContextKeyBindings() []*Binding {
|
|||||||
bindings = append(bindings, []*Binding{
|
bindings = append(bindings, []*Binding{
|
||||||
{
|
{
|
||||||
ViewName: listContext.ViewName,
|
ViewName: listContext.ViewName,
|
||||||
Contexts: []string{listContext.ContextKey},
|
Contexts: []string{string(listContext.ContextKey)},
|
||||||
Key: gui.getKey(keybindingConfig.Universal.StartSearch),
|
Key: gui.getKey(keybindingConfig.Universal.StartSearch),
|
||||||
Handler: func() error { return openSearchHandler(listContext.ViewName) },
|
Handler: func() error { return openSearchHandler(listContext.ViewName) },
|
||||||
Description: gui.Tr.LcStartSearch,
|
Description: gui.Tr.LcStartSearch,
|
||||||
@ -587,7 +587,7 @@ func (gui *Gui) getListContextKeyBindings() []*Binding {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
ViewName: listContext.ViewName,
|
ViewName: listContext.ViewName,
|
||||||
Contexts: []string{listContext.ContextKey},
|
Contexts: []string{string(listContext.ContextKey)},
|
||||||
Key: gui.getKey(keybindingConfig.Universal.GotoBottom),
|
Key: gui.getKey(keybindingConfig.Universal.GotoBottom),
|
||||||
Handler: gotoBottomHandler,
|
Handler: gotoBottomHandler,
|
||||||
Description: gui.Tr.LcGotoBottom,
|
Description: gui.Tr.LcGotoBottom,
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import "os/exec"
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
)
|
||||||
|
|
||||||
type viewUpdateOpts struct {
|
type viewUpdateOpts struct {
|
||||||
title string
|
title string
|
||||||
@ -42,7 +46,7 @@ func (t *renderStringTask) GetKind() TaskKind {
|
|||||||
return RENDER_STRING
|
return RENDER_STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createRenderStringTask(str string) *renderStringTask {
|
func NewRenderStringTask(str string) *renderStringTask {
|
||||||
return &renderStringTask{str: str}
|
return &renderStringTask{str: str}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ func (t *renderStringWithoutScrollTask) GetKind() TaskKind {
|
|||||||
return RENDER_STRING_WITHOUT_SCROLL
|
return RENDER_STRING_WITHOUT_SCROLL
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createRenderStringWithoutScrollTask(str string) *renderStringWithoutScrollTask {
|
func NewRenderStringWithoutScrollTask(str string) *renderStringWithoutScrollTask {
|
||||||
return &renderStringWithoutScrollTask{str: str}
|
return &renderStringWithoutScrollTask{str: str}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +71,11 @@ func (t *runCommandTask) GetKind() TaskKind {
|
|||||||
return RUN_COMMAND
|
return RUN_COMMAND
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createRunCommandTask(cmd *exec.Cmd) *runCommandTask {
|
func NewRunCommandTask(cmd *exec.Cmd) *runCommandTask {
|
||||||
return &runCommandTask{cmd: cmd}
|
return &runCommandTask{cmd: cmd}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createRunCommandTaskWithPrefix(cmd *exec.Cmd, prefix string) *runCommandTask {
|
func NewRunCommandTaskWithPrefix(cmd *exec.Cmd, prefix string) *runCommandTask {
|
||||||
return &runCommandTask{cmd: cmd, prefix: prefix}
|
return &runCommandTask{cmd: cmd, prefix: prefix}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +88,7 @@ func (t *runPtyTask) GetKind() TaskKind {
|
|||||||
return RUN_PTY
|
return RUN_PTY
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createRunPtyTask(cmd *exec.Cmd) *runPtyTask {
|
func NewRunPtyTask(cmd *exec.Cmd) *runPtyTask {
|
||||||
return &runPtyTask{cmd: cmd}
|
return &runPtyTask{cmd: cmd}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,18 +138,12 @@ func (gui *Gui) runTaskForView(viewName string, task updateTask) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshMainView(opts *viewUpdateOpts, viewName string) error {
|
func (gui *Gui) refreshMainView(opts *viewUpdateOpts, view *gocui.View) error {
|
||||||
view, err := gui.g.View(viewName)
|
|
||||||
if err != nil {
|
|
||||||
gui.Log.Error(err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
view.Title = opts.title
|
view.Title = opts.title
|
||||||
view.Wrap = !opts.noWrap
|
view.Wrap = !opts.noWrap
|
||||||
view.Highlight = opts.highlight
|
view.Highlight = opts.highlight
|
||||||
|
|
||||||
if err := gui.runTaskForView(viewName, opts.task); err != nil {
|
if err := gui.runTaskForView(view.Name(), opts.task); err != nil {
|
||||||
gui.Log.Error(err)
|
gui.Log.Error(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -155,19 +153,19 @@ func (gui *Gui) refreshMainView(opts *viewUpdateOpts, viewName string) error {
|
|||||||
|
|
||||||
func (gui *Gui) refreshMainViews(opts refreshMainOpts) error {
|
func (gui *Gui) refreshMainViews(opts refreshMainOpts) error {
|
||||||
if opts.main != nil {
|
if opts.main != nil {
|
||||||
if err := gui.refreshMainView(opts.main, "main"); err != nil {
|
if err := gui.refreshMainView(opts.main, gui.Views.Main); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.secondary != nil {
|
||||||
|
if err := gui.refreshMainView(opts.secondary, gui.Views.Secondary); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.splitMainPanel(opts.secondary != nil)
|
gui.splitMainPanel(opts.secondary != nil)
|
||||||
|
|
||||||
if opts.secondary != nil {
|
|
||||||
if err := gui.refreshMainView(opts.secondary, "secondary"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +174,7 @@ func (gui *Gui) splitMainPanel(splitMainPanel bool) {
|
|||||||
|
|
||||||
// no need to set view on bottom when splitMainPanel is false: it will have zero size anyway thanks to our view arrangement code.
|
// no need to set view on bottom when splitMainPanel is false: it will have zero size anyway thanks to our view arrangement code.
|
||||||
if splitMainPanel {
|
if splitMainPanel {
|
||||||
_, _ = gui.g.SetViewOnTop("secondary")
|
gui.Views.Secondary.Visible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ func (gui *Gui) getMenuOptions() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleMenuClose() error {
|
func (gui *Gui) handleMenuClose() error {
|
||||||
_ = gui.g.DeleteView("menu")
|
|
||||||
return gui.returnFromContext()
|
return gui.returnFromContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ func (gui *Gui) refreshMergePanel() error {
|
|||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
title: "",
|
title: "",
|
||||||
task: gui.createRenderStringTask(err.Error()),
|
task: NewRenderStringTask(err.Error()),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ func (gui *Gui) refreshMergePanel() error {
|
|||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
title: gui.Tr.MergeConflictsTitle,
|
title: gui.Tr.MergeConflictsTitle,
|
||||||
task: gui.createRenderStringWithoutScrollTask(content),
|
task: NewRenderStringWithoutScrollTask(content),
|
||||||
noWrap: true,
|
noWrap: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -236,7 +236,8 @@ func (gui *Gui) scrollToConflict() error {
|
|||||||
if len(panelState.Conflicts) == 0 {
|
if len(panelState.Conflicts) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mergingView := gui.getMainView()
|
|
||||||
|
mergingView := gui.Views.Main
|
||||||
conflict := panelState.Conflicts[panelState.ConflictIndex]
|
conflict := panelState.Conflicts[panelState.ConflictIndex]
|
||||||
ox, _ := mergingView.Origin()
|
ox, _ := mergingView.Origin()
|
||||||
_, height := mergingView.Size()
|
_, height := mergingView.Size()
|
||||||
@ -269,7 +270,7 @@ func (gui *Gui) handleEscapeMerge() error {
|
|||||||
}
|
}
|
||||||
// it's possible this method won't be called from the merging view so we need to
|
// it's possible this method won't be called from the merging view so we need to
|
||||||
// ensure we only 'return' focus if we already have it
|
// ensure we only 'return' focus if we already have it
|
||||||
if gui.g.CurrentView() == gui.getMainView() {
|
if gui.g.CurrentView() == gui.Views.Main {
|
||||||
return gui.pushContext(gui.State.Contexts.Files)
|
return gui.pushContext(gui.State.Contexts.Files)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -22,10 +22,8 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *lBlPanelSt
|
|||||||
return gui.handleEscapePatchBuildingPanel()
|
return gui.handleEscapePatchBuildingPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.splitMainPanel(true)
|
gui.Views.Main.Title = "Patch"
|
||||||
|
gui.Views.Secondary.Title = "Custom Patch"
|
||||||
gui.getMainView().Title = "Patch"
|
|
||||||
gui.getSecondaryView().Title = "Custom Patch"
|
|
||||||
|
|
||||||
// get diff from commit file that's currently selected
|
// get diff from commit file that's currently selected
|
||||||
node := gui.getSelectedCommitFileNode()
|
node := gui.getSelectedCommitFileNode()
|
||||||
@ -125,7 +123,7 @@ func (gui *Gui) secondaryPatchPanelUpdateOpts() *viewUpdateOpts {
|
|||||||
title: "Custom Patch",
|
title: "Custom Patch",
|
||||||
noWrap: true,
|
noWrap: true,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
task: gui.createRenderStringWithoutScrollTask(patch),
|
task: NewRenderStringWithoutScrollTask(patch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ func (gui *Gui) onResize() error {
|
|||||||
if gui.State.Ptmx == nil {
|
if gui.State.Ptmx == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mainView := gui.getMainView()
|
width, height := gui.Views.Main.Size()
|
||||||
width, height := mainView.Size()
|
|
||||||
|
|
||||||
if err := pty.Setsize(gui.State.Ptmx, &pty.Winsize{Cols: uint16(width), Rows: uint16(height)}); err != nil {
|
if err := pty.Setsize(gui.State.Ptmx, &pty.Winsize{Cols: uint16(width), Rows: uint16(height)}); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -31,7 +30,7 @@ func (gui *Gui) onResize() error {
|
|||||||
// pseudo-terminal meaning we'll get the behaviour we want from the underlying
|
// pseudo-terminal meaning we'll get the behaviour we want from the underlying
|
||||||
// command.
|
// command.
|
||||||
func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd, prefix string) error {
|
func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd, prefix string) error {
|
||||||
width, _ := gui.getMainView().Size()
|
width, _ := gui.Views.Main.Size()
|
||||||
pager := gui.GitCommand.GetPager(width)
|
pager := gui.GitCommand.GetPager(width)
|
||||||
|
|
||||||
if pager == "" {
|
if pager == "" {
|
||||||
|
@ -40,7 +40,7 @@ func (gui *Gui) handleShowAllBranchLogs() error {
|
|||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.Config.GetUserConfig().Git.AllBranchesLogCmd,
|
gui.Config.GetUserConfig().Git.AllBranchesLogCmd,
|
||||||
)
|
)
|
||||||
task := gui.createRunPtyTask(cmd)
|
task := NewRunPtyTask(cmd)
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
|
@ -20,13 +20,13 @@ func (gui *Gui) handleReflogCommitSelect() error {
|
|||||||
commit := gui.getSelectedReflogCommit()
|
commit := gui.getSelectedReflogCommit()
|
||||||
var task updateTask
|
var task updateTask
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
task = gui.createRenderStringTask("No reflog history")
|
task = NewRenderStringTask("No reflog history")
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
||||||
)
|
)
|
||||||
|
|
||||||
task = gui.createRunPtyTask(cmd)
|
task = NewRunPtyTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
|
@ -22,12 +22,12 @@ func (gui *Gui) handleRemoteBranchSelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
remoteBranch := gui.getSelectedRemoteBranch()
|
remoteBranch := gui.getSelectedRemoteBranch()
|
||||||
if remoteBranch == nil {
|
if remoteBranch == nil {
|
||||||
task = gui.createRenderStringTask("No branches for this remote")
|
task = NewRenderStringTask("No branches for this remote")
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.GetBranchGraphCmdStr(remoteBranch.FullName()),
|
gui.GitCommand.GetBranchGraphCmdStr(remoteBranch.FullName()),
|
||||||
)
|
)
|
||||||
task = gui.createRunCommandTask(cmd)
|
task = NewRunCommandTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
|
@ -24,9 +24,9 @@ func (gui *Gui) handleRemoteSelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
remote := gui.getSelectedRemote()
|
remote := gui.getSelectedRemote()
|
||||||
if remote == nil {
|
if remote == nil {
|
||||||
task = gui.createRenderStringTask("No remotes")
|
task = NewRenderStringTask("No remotes")
|
||||||
} else {
|
} else {
|
||||||
task = gui.createRenderStringTask(fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n")))
|
task = NewRenderStringTask(fmt.Sprintf("%s\nUrls:\n%s", utils.ColoredString(remote.Name, color.FgGreen), strings.Join(remote.Urls, "\n")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
@ -57,12 +57,7 @@ func (gui *Gui) refreshRemotes() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
branchesView := gui.getBranchesView()
|
return gui.postRefreshUpdate(gui.mustContextForContextKey(ContextKey(gui.Views.Branches.Context)))
|
||||||
if branchesView != nil {
|
|
||||||
return gui.postRefreshUpdate(gui.mustContextForContextKey(branchesView.Context))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleRemoteEnter() error {
|
func (gui *Gui) handleRemoteEnter() error {
|
||||||
|
@ -26,7 +26,7 @@ func (gui *Gui) handleOpenSearch(viewName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleSearch() error {
|
func (gui *Gui) handleSearch() error {
|
||||||
gui.State.Searching.searchString = gui.getSearchView().Buffer()
|
gui.State.Searching.searchString = gui.Views.Search.Buffer()
|
||||||
if err := gui.returnFromContext(); err != nil {
|
if err := gui.returnFromContext(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ func (gui *Gui) nextSideWindow() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := gui.resetOrigin(gui.getMainView()); err != nil {
|
if err := gui.resetOrigin(gui.Views.Main); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ func (gui *Gui) previousSideWindow() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := gui.resetOrigin(gui.getMainView()); err != nil {
|
if err := gui.resetOrigin(gui.Views.Main); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,11 +26,11 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
|
|||||||
}
|
}
|
||||||
|
|
||||||
if secondaryFocused {
|
if secondaryFocused {
|
||||||
gui.getMainView().Title = gui.Tr.StagedChanges
|
gui.Views.Main.Title = gui.Tr.StagedChanges
|
||||||
gui.getSecondaryView().Title = gui.Tr.UnstagedChanges
|
gui.Views.Secondary.Title = gui.Tr.UnstagedChanges
|
||||||
} else {
|
} else {
|
||||||
gui.getMainView().Title = gui.Tr.UnstagedChanges
|
gui.Views.Main.Title = gui.Tr.UnstagedChanges
|
||||||
gui.getSecondaryView().Title = gui.Tr.StagedChanges
|
gui.Views.Secondary.Title = gui.Tr.StagedChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
// note for custom diffs, we'll need to send a flag here saying not to use the custom diff
|
// note for custom diffs, we'll need to send a flag here saying not to use the custom diff
|
||||||
@ -63,7 +63,7 @@ func (gui *Gui) handleTogglePanelClick() error {
|
|||||||
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
|
||||||
state.SecondaryFocused = !state.SecondaryFocused
|
state.SecondaryFocused = !state.SecondaryFocused
|
||||||
|
|
||||||
return gui.refreshStagingPanel(false, gui.getSecondaryView().SelectedLineIdx(), state)
|
return gui.refreshStagingPanel(false, gui.Views.Secondary.SelectedLineIdx(), state)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ func (gui *Gui) handleStashEntrySelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
stashEntry := gui.getSelectedStashEntry()
|
stashEntry := gui.getSelectedStashEntry()
|
||||||
if stashEntry == nil {
|
if stashEntry == nil {
|
||||||
task = gui.createRenderStringTask(gui.Tr.NoStashEntries)
|
task = NewRenderStringTask(gui.Tr.NoStashEntries)
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.ShowStashEntryCmdStr(stashEntry.Index),
|
gui.GitCommand.ShowStashEntryCmdStr(stashEntry.Index),
|
||||||
)
|
)
|
||||||
task = gui.createRunPtyTask(cmd)
|
task = NewRunPtyTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
|
@ -43,7 +43,7 @@ func (gui *Gui) refreshStatus() {
|
|||||||
status += fmt.Sprintf("%s → %s ", repoName, name)
|
status += fmt.Sprintf("%s → %s ", repoName, name)
|
||||||
|
|
||||||
gui.g.Update(func(*gocui.Gui) error {
|
gui.g.Update(func(*gocui.Gui) error {
|
||||||
gui.setViewContent(gui.getStatusView(), status)
|
gui.setViewContent(gui.Views.Status, status)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ func (gui *Gui) handleStatusClick() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cx, _ := gui.getStatusView().Cursor()
|
cx, _ := gui.Views.Status.Cursor()
|
||||||
upstreamStatus := fmt.Sprintf("↑%s↓%s", currentBranch.Pushables, currentBranch.Pullables)
|
upstreamStatus := fmt.Sprintf("↑%s↓%s", currentBranch.Pushables, currentBranch.Pullables)
|
||||||
repoName := utils.GetCurrentRepoName()
|
repoName := utils.GetCurrentRepoName()
|
||||||
switch gui.GitCommand.WorkingTreeState() {
|
switch gui.GitCommand.WorkingTreeState() {
|
||||||
@ -121,7 +121,7 @@ func (gui *Gui) handleStatusSelect() error {
|
|||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
main: &viewUpdateOpts{
|
main: &viewUpdateOpts{
|
||||||
title: "",
|
title: "",
|
||||||
task: gui.createRenderStringTask(dashboardString),
|
task: NewRenderStringTask(dashboardString),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@ func (gui *Gui) handleSubCommitSelect() error {
|
|||||||
commit := gui.getSelectedSubCommit()
|
commit := gui.getSelectedSubCommit()
|
||||||
var task updateTask
|
var task updateTask
|
||||||
if commit == nil {
|
if commit == nil {
|
||||||
task = gui.createRenderStringTask("No commits")
|
task = NewRenderStringTask("No commits")
|
||||||
} else {
|
} else {
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
gui.GitCommand.ShowCmdStr(commit.Sha, gui.State.Modes.Filtering.GetPath()),
|
||||||
)
|
)
|
||||||
|
|
||||||
task = gui.createRunPtyTask(cmd)
|
task = NewRunPtyTask(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
@ -94,13 +94,13 @@ func (gui *Gui) switchToSubCommitsContext(refName string) error {
|
|||||||
gui.State.SubCommits = commits
|
gui.State.SubCommits = commits
|
||||||
gui.State.Panels.SubCommits.refName = refName
|
gui.State.Panels.SubCommits.refName = refName
|
||||||
gui.State.Panels.SubCommits.SelectedLineIdx = 0
|
gui.State.Panels.SubCommits.SelectedLineIdx = 0
|
||||||
gui.State.Contexts.SubCommits.SetParentContext(gui.currentSideContext())
|
gui.State.Contexts.SubCommits.SetParentContext(gui.currentSideListContext())
|
||||||
|
|
||||||
return gui.pushContext(gui.State.Contexts.SubCommits)
|
return gui.pushContext(gui.State.Contexts.SubCommits)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleSwitchToSubCommits() error {
|
func (gui *Gui) handleSwitchToSubCommits() error {
|
||||||
currentContext := gui.currentSideContext()
|
currentContext := gui.currentSideListContext()
|
||||||
if currentContext == nil {
|
if currentContext == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func (gui *Gui) handleSubmoduleSelect() error {
|
|||||||
var task updateTask
|
var task updateTask
|
||||||
submodule := gui.getSelectedSubmodule()
|
submodule := gui.getSelectedSubmodule()
|
||||||
if submodule == nil {
|
if submodule == nil {
|
||||||
task = gui.createRenderStringTask("No submodules")
|
task = NewRenderStringTask("No submodules")
|
||||||
} else {
|
} else {
|
||||||
prefix := fmt.Sprintf(
|
prefix := fmt.Sprintf(
|
||||||
"Name: %s\nPath: %s\nUrl: %s\n\n",
|
"Name: %s\nPath: %s\nUrl: %s\n\n",
|
||||||
@ -35,11 +35,11 @@ func (gui *Gui) handleSubmoduleSelect() error {
|
|||||||
|
|
||||||
file := gui.fileForSubmodule(submodule)
|
file := gui.fileForSubmodule(submodule)
|
||||||
if file == nil {
|
if file == nil {
|
||||||
task = gui.createRenderStringTask(prefix)
|
task = NewRenderStringTask(prefix)
|
||||||
} else {
|
} else {
|
||||||
cmdStr := gui.GitCommand.WorktreeFileDiffCmdStr(file, false, !file.HasUnstagedChanges && file.HasStagedChanges)
|
cmdStr := gui.GitCommand.WorktreeFileDiffCmdStr(file, false, !file.HasUnstagedChanges && file.HasStagedChanges)
|
||||||
cmd := gui.OSCommand.ExecutableFromString(cmdStr)
|
cmd := gui.OSCommand.ExecutableFromString(cmdStr)
|
||||||
task = gui.createRunCommandTaskWithPrefix(cmd, prefix)
|
task = NewRunCommandTaskWithPrefix(cmd, prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,8 @@ func (gui *Gui) getSelectedSuggestion() *types.Suggestion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) setSuggestions(suggestions []*types.Suggestion) {
|
func (gui *Gui) setSuggestions(suggestions []*types.Suggestion) {
|
||||||
view := gui.getSuggestionsView()
|
|
||||||
if view == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.State.Suggestions = suggestions
|
gui.State.Suggestions = suggestions
|
||||||
gui.State.Panels.Suggestions.SelectedLineIdx = 0
|
gui.State.Panels.Suggestions.SelectedLineIdx = 0
|
||||||
_ = gui.resetOrigin(view)
|
_ = gui.resetOrigin(gui.Views.Suggestions)
|
||||||
_ = gui.State.Contexts.Suggestions.HandleRender()
|
_ = gui.State.Contexts.Suggestions.HandleRender()
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// list panel functions
|
|
||||||
|
|
||||||
func (gui *Gui) getSelectedTag() *models.Tag {
|
func (gui *Gui) getSelectedTag() *models.Tag {
|
||||||
selectedLine := gui.State.Panels.Tags.SelectedLineIdx
|
selectedLine := gui.State.Panels.Tags.SelectedLineIdx
|
||||||
if selectedLine == -1 || len(gui.State.Tags) == 0 {
|
if selectedLine == -1 || len(gui.State.Tags) == 0 {
|
||||||
@ -16,100 +14,6 @@ func (gui *Gui) getSelectedTag() *models.Tag {
|
|||||||
return gui.State.Tags[selectedLine]
|
return gui.State.Tags[selectedLine]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleTagSelect() error {
|
|
||||||
var task updateTask
|
|
||||||
tag := gui.getSelectedTag()
|
|
||||||
if tag == nil {
|
|
||||||
task = gui.createRenderStringTask("No tags")
|
|
||||||
} else {
|
|
||||||
cmd := gui.OSCommand.ExecutableFromString(
|
|
||||||
gui.GitCommand.GetBranchGraphCmdStr(tag.Name),
|
|
||||||
)
|
|
||||||
task = gui.createRunCommandTask(cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gui.refreshMainViews(refreshMainOpts{
|
|
||||||
main: &viewUpdateOpts{
|
|
||||||
title: "Tag",
|
|
||||||
task: task,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) refreshTags() error {
|
|
||||||
tags, err := gui.GitCommand.GetTags()
|
|
||||||
if err != nil {
|
|
||||||
return gui.surfaceError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.State.Tags = tags
|
|
||||||
|
|
||||||
return gui.postRefreshUpdate(gui.State.Contexts.Tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleCheckoutTag() error {
|
|
||||||
tag := gui.getSelectedTag()
|
|
||||||
if tag == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := gui.handleCheckoutRef(tag.Name, handleCheckoutRefOptions{}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return gui.pushContext(gui.State.Contexts.Branches)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleDeleteTag() error {
|
|
||||||
tag := gui.getSelectedTag()
|
|
||||||
if tag == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt := utils.ResolvePlaceholderString(
|
|
||||||
gui.Tr.DeleteTagPrompt,
|
|
||||||
map[string]string{
|
|
||||||
"tagName": tag.Name,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return gui.ask(askOpts{
|
|
||||||
title: gui.Tr.DeleteTagTitle,
|
|
||||||
prompt: prompt,
|
|
||||||
handleConfirm: func() error {
|
|
||||||
if err := gui.GitCommand.DeleteTag(tag.Name); err != nil {
|
|
||||||
return gui.surfaceError(err)
|
|
||||||
}
|
|
||||||
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []RefreshableView{COMMITS, TAGS}})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handlePushTag() error {
|
|
||||||
tag := gui.getSelectedTag()
|
|
||||||
if tag == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
title := utils.ResolvePlaceholderString(
|
|
||||||
gui.Tr.PushTagTitle,
|
|
||||||
map[string]string{
|
|
||||||
"tagName": tag.Name,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return gui.prompt(promptOpts{
|
|
||||||
title: title,
|
|
||||||
initialContent: "origin",
|
|
||||||
handleConfirm: func(response string) error {
|
|
||||||
return gui.WithWaitingStatus(gui.Tr.PushingTagStatus, func() error {
|
|
||||||
err := gui.GitCommand.PushTag(response, tag.Name, gui.promptUserForCredential)
|
|
||||||
gui.handleCredentialsPopup(err)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleCreateTag() error {
|
func (gui *Gui) handleCreateTag() error {
|
||||||
return gui.prompt(promptOpts{
|
return gui.prompt(promptOpts{
|
||||||
title: gui.Tr.CreateTagTitle,
|
title: gui.Tr.CreateTagTitle,
|
||||||
@ -136,11 +40,98 @@ func (gui *Gui) handleCreateTag() error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleCreateResetToTagMenu() error {
|
// tag-specific handlers
|
||||||
|
// view model would need to raise an event called 'tag selected', perhaps containing a tag. The listener would _be_ the main view, or the main context, and it would be able to render to itself.
|
||||||
|
func (gui *Gui) handleTagSelect() error {
|
||||||
|
var task updateTask
|
||||||
|
tag := gui.getSelectedTag()
|
||||||
|
if tag == nil {
|
||||||
|
task = NewRenderStringTask("No tags")
|
||||||
|
} else {
|
||||||
|
cmd := gui.OSCommand.ExecutableFromString(
|
||||||
|
gui.GitCommand.GetBranchGraphCmdStr(tag.Name),
|
||||||
|
)
|
||||||
|
task = NewRunCommandTask(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui.refreshMainViews(refreshMainOpts{
|
||||||
|
main: &viewUpdateOpts{
|
||||||
|
title: "Tag",
|
||||||
|
task: task,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a controller: it can't access tags directly. Or can it? It should be able to get but not set. But that's exactly what I'm doing here, setting it. but through a mutator which encapsulates the event.
|
||||||
|
func (gui *Gui) refreshTags() error {
|
||||||
|
tags, err := gui.GitCommand.GetTags()
|
||||||
|
if err != nil {
|
||||||
|
return gui.surfaceError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.State.Tags = tags
|
||||||
|
|
||||||
|
return gui.postRefreshUpdate(gui.State.Contexts.Tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) withSelectedTag(f func(tag *models.Tag) error) func() error {
|
||||||
tag := gui.getSelectedTag()
|
tag := gui.getSelectedTag()
|
||||||
if tag == nil {
|
if tag == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return func() error { return f(tag) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleCheckoutTag(tag *models.Tag) error {
|
||||||
|
if err := gui.handleCheckoutRef(tag.Name, handleCheckoutRefOptions{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return gui.pushContext(gui.State.Contexts.Branches)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleDeleteTag(tag *models.Tag) error {
|
||||||
|
prompt := utils.ResolvePlaceholderString(
|
||||||
|
gui.Tr.DeleteTagPrompt,
|
||||||
|
map[string]string{
|
||||||
|
"tagName": tag.Name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return gui.ask(askOpts{
|
||||||
|
title: gui.Tr.DeleteTagTitle,
|
||||||
|
prompt: prompt,
|
||||||
|
handleConfirm: func() error {
|
||||||
|
if err := gui.GitCommand.DeleteTag(tag.Name); err != nil {
|
||||||
|
return gui.surfaceError(err)
|
||||||
|
}
|
||||||
|
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []RefreshableView{COMMITS, TAGS}})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handlePushTag(tag *models.Tag) error {
|
||||||
|
title := utils.ResolvePlaceholderString(
|
||||||
|
gui.Tr.PushTagTitle,
|
||||||
|
map[string]string{
|
||||||
|
"tagName": tag.Name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return gui.prompt(promptOpts{
|
||||||
|
title: title,
|
||||||
|
initialContent: "origin",
|
||||||
|
handleConfirm: func(response string) error {
|
||||||
|
return gui.WithWaitingStatus(gui.Tr.PushingTagStatus, func() error {
|
||||||
|
err := gui.GitCommand.PushTag(response, tag.Name, gui.promptUserForCredential)
|
||||||
|
gui.handleCredentialsPopup(err)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) handleCreateResetToTagMenu(tag *models.Tag) error {
|
||||||
return gui.createResetMenu(tag.Name)
|
return gui.createResetMenu(tag.Name)
|
||||||
}
|
}
|
||||||
|
@ -241,88 +241,6 @@ func (gui *Gui) renderOptionsMap(optionsMap map[string]string) {
|
|||||||
gui.renderString("options", gui.optionsMapToString(optionsMap))
|
gui.renderString("options", gui.optionsMapToString(optionsMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getFilesView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("files")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getCommitFilesView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("commitFiles")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getCommitsView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("commits")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getCredentialsView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("commits")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getCommitMessageView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("commitMessage")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getBranchesView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("branches")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getMainView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("main")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getSuggestionsView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("suggestions")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getSecondaryView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("secondary")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// currently unused
|
|
||||||
// func (gui *Gui) getStashView() *gocui.View {
|
|
||||||
// v, _ := gui.g.View("stash")
|
|
||||||
// return v
|
|
||||||
// }
|
|
||||||
|
|
||||||
// currently unused
|
|
||||||
// func (gui *Gui) getCommitFilesView() *gocui.View {
|
|
||||||
// v, _ := gui.g.View("commitFiles")
|
|
||||||
// return v
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (gui *Gui) getMenuView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("menu")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getSearchView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("search")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getStatusView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("status")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("confirmation")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getInformationView() *gocui.View {
|
|
||||||
v, _ := gui.g.View("information")
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) trimmedContent(v *gocui.View) string {
|
func (gui *Gui) trimmedContent(v *gocui.View) string {
|
||||||
return strings.TrimSpace(v.Buffer())
|
return strings.TrimSpace(v.Buffer())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user