1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
package filetree
import (
"strings"
"sync"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
)
type ICommitFileTreeViewModel interface {
ICommitFileTree
types.IListCursor
GetRef() models.Ref
SetRef(models.Ref)
GetRefRange() *types.RefRange // can be nil, in which case GetRef should be used
SetRefRange(*types.RefRange) // should be set to nil when selection is not a range
GetCanRebase() bool
SetCanRebase(bool)
}
type CommitFileTreeViewModel struct {
sync.RWMutex
types.IListCursor
ICommitFileTree
// this is e.g. the commit for which we're viewing the files, if there is no
// range selection, or if the range selection can't be used for some reason
ref models.Ref
// this is a commit range for which we're viewing the files. Can be nil, in
// which case ref is used.
refRange *types.RefRange
// we set this to true when you're viewing the files within the checked-out branch's commits.
// If you're viewing the files of some random other branch we can't do any rebase stuff.
canRebase bool
}
var _ ICommitFileTreeViewModel = &CommitFileTreeViewModel{}
func NewCommitFileTreeViewModel(getFiles func() []*models.CommitFile, common *common.Common, showTree bool) *CommitFileTreeViewModel {
fileTree := NewCommitFileTree(getFiles, common, showTree)
listCursor := traits.NewListCursor(fileTree.Len)
return &CommitFileTreeViewModel{
ICommitFileTree: fileTree,
IListCursor: listCursor,
ref: nil,
refRange: nil,
canRebase: false,
}
}
func (self *CommitFileTreeViewModel) GetRef() models.Ref {
return self.ref
}
func (self *CommitFileTreeViewModel) SetRef(ref models.Ref) {
self.ref = ref
}
func (self *CommitFileTreeViewModel) GetRefRange() *types.RefRange {
return self.refRange
}
func (self *CommitFileTreeViewModel) SetRefRange(refsForRange *types.RefRange) {
self.refRange = refsForRange
}
func (self *CommitFileTreeViewModel) GetCanRebase() bool {
return self.canRebase
}
func (self *CommitFileTreeViewModel) SetCanRebase(canRebase bool) {
self.canRebase = canRebase
}
func (self *CommitFileTreeViewModel) GetSelected() *CommitFileNode {
if self.Len() == 0 {
return nil
}
return self.Get(self.GetSelectedLineIdx())
}
func (self *CommitFileTreeViewModel) GetSelectedItemId() string {
item := self.GetSelected()
if item == nil {
return ""
}
return item.ID()
}
func (self *CommitFileTreeViewModel) GetSelectedItems() ([]*CommitFileNode, int, int) {
if self.Len() == 0 {
return nil, 0, 0
}
startIdx, endIdx := self.GetSelectionRange()
nodes := []*CommitFileNode{}
for i := startIdx; i <= endIdx; i++ {
nodes = append(nodes, self.Get(i))
}
return nodes, startIdx, endIdx
}
func (self *CommitFileTreeViewModel) GetSelectedItemIds() ([]string, int, int) {
selectedItems, startIdx, endIdx := self.GetSelectedItems()
ids := lo.Map(selectedItems, func(item *CommitFileNode, _ int) string {
return item.ID()
})
return ids, startIdx, endIdx
}
func (self *CommitFileTreeViewModel) GetSelectedFile() *models.CommitFile {
node := self.GetSelected()
if node == nil {
return nil
}
return node.File
}
func (self *CommitFileTreeViewModel) GetSelectedPath() string {
node := self.GetSelected()
if node == nil {
return ""
}
return node.GetPath()
}
// duplicated from file_tree_view_model.go. Generics will help here
func (self *CommitFileTreeViewModel) ToggleShowTree() {
selectedNode := self.GetSelected()
self.ICommitFileTree.ToggleShowTree()
if selectedNode == nil {
return
}
path := selectedNode.path
if self.InTreeMode() {
self.ExpandToPath(path)
} else if len(selectedNode.Children) > 0 {
path = selectedNode.GetLeaves()[0].path
}
index, found := self.GetIndexForPath(path)
if found {
self.SetSelection(index)
}
}
func (self *CommitFileTreeViewModel) CollapseAll() {
selectedNode := self.GetSelected()
self.ICommitFileTree.CollapseAll()
if selectedNode == nil {
return
}
topLevelPath := strings.Split(selectedNode.path, "/")[0]
index, found := self.GetIndexForPath(topLevelPath)
if found {
self.SetSelectedLineIdx(index)
}
}
func (self *CommitFileTreeViewModel) ExpandAll() {
selectedNode := self.GetSelected()
self.ICommitFileTree.ExpandAll()
if selectedNode == nil {
return
}
index, found := self.GetIndexForPath(selectedNode.path)
if found {
self.SetSelectedLineIdx(index)
}
}
// Try to select the given path if present. If it doesn't exist, or one of the parent directories is
// collapsed, do nothing.
// Note that filepath is an actual file path, not an internal tree path as with e.g.
// ToggleCollapsed. It must be a relative path (relative to the repo root), and it must contain
// forward slashes rather than backslashes even on Windows.
func (self *CommitFileTreeViewModel) SelectPath(filepath string, showRootItem bool) {
index, found := self.GetIndexForPath(InternalTreePathForFilePath(filepath, showRootItem))
if found {
self.SetSelection(index)
}
}
|