Skip to content

VIM Visual Mode #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/ui/manga_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ func newMangaPage(manga *mangodex.Manga) *MangaPage {
Info: info,
Table: table,
sWrap: &utils.SelectorWrapper{
Selection: map[int]struct{}{},
Selection: map[int]struct{}{},
VisualStart: -1,
},
cWrap: &utils.ContextWrapper{
Ctx: ctx,
Expand Down
61 changes: 61 additions & 0 deletions app/ui/page_inputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ func (p *MangaPage) setHandlers(cancel context.CancelFunc) {
return event
})

p.Table.SetSelectionChangedFunc(func(row, _column int) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment on what this binding does would be useful. See line 182 of same file for example.

if p.sWrap.IsInVisualMode() {
p.selectRange(min(row, p.sWrap.VisualStart), max(row, p.sWrap.VisualStart))
}
})

// Set table selected function.
p.Table.SetSelectedFunc(func(row, _ int) {
log.Println("Creating and showing confirm download modal...")
Expand All @@ -203,16 +209,26 @@ func (p *MangaPage) setHandlers(cancel context.CancelFunc) {

// Set table input captures.
p.Table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {

switch event.Key() {
case tcell.KeyCtrlE: // User selects this manga row.
p.ctrlEInput()
return event
case tcell.KeyCtrlA: // User wants to toggle select All.
p.ctrlAInput()
return event
case tcell.KeyCtrlR: // User wants to toggle read status for Selection.
p.ctrlRInput()
return event
case tcell.KeyCtrlQ:
p.ctrlQInput()
return event
}

if event.Rune() == 'v' || event.Rune() == 'V' {
p.shiftVInput()
}

return event
})
}
Expand All @@ -234,6 +250,51 @@ func (p *MangaPage) ctrlAInput() {
p.markAll()
}

func (p *MangaPage) selectRange(from, to int) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment for this function and the one below would also be great.

start := min(from, to)
end := max(from, to)

for row := 1; row < p.Table.GetRowCount(); row++ {
if row < start || row > end {
if p.sWrap.HasSelection(row) {
p.markUnselected(row)
}
} else {
if !p.sWrap.HasSelection(row) {
p.markSelected(row)
}
}
}
}

func min(a, b int) int {
if a < b {
return a
}
return b
}

func max(a, b int) int {
if a > b {
return a
}
return b
}

func (p *MangaPage) shiftVInput() {
if p.sWrap.IsInVisualMode() {
p.sWrap.StopVisualSelection()
for row := 1; row < p.Table.GetRowCount(); row++ {
if p.sWrap.HasSelection(row) {
p.markUnselected(row)
}
}
} else {
row, _ := p.Table.GetSelection()
p.sWrap.StartVisualSelection(row)
}
}

// ctrlRInput : Allows user to toggle read status for a chapter.
func (p *MangaPage) ctrlRInput() {
modal := confirmModal(utils.ToggleReadChapterModalID,
Expand Down
18 changes: 15 additions & 3 deletions app/ui/utils/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package utils
// SelectorWrapper : A wrapper to store selections. Used by the manga page to
// keep track of selections.
type SelectorWrapper struct {
Selection map[int]struct{} // Keep track of which chapters have been selected by user.
All bool // Keep track of whether user has selected All or not.
Selection map[int]struct{} // Keep track of which chapters have been selected by user.
All bool // Keep track of whether user has selected All or not.
VisualStart int // Keeps track of the start of the visual selection. -1 If none.
}

// HasSelections : Checks whether there are currently selections.
Expand All @@ -24,7 +25,6 @@ func (s *SelectorWrapper) CopySelection(row int) map[int]struct{} {
if !s.HasSelections() {
s.AddSelection(row)
}

selection := map[int]struct{}{}
for se := range s.Selection {
selection[se] = struct{}{}
Expand All @@ -47,3 +47,15 @@ func (s *SelectorWrapper) AddSelection(row int) {
func (s *SelectorWrapper) RemoveSelection(row int) {
delete(s.Selection, row)
}

func (s *SelectorWrapper) IsInVisualMode() bool {
return s.VisualStart != -1
}

func (s *SelectorWrapper) StartVisualSelection(row int) {
s.VisualStart = row
}

func (s *SelectorWrapper) StopVisualSelection() {
s.VisualStart = -1
}