Implement scrolling by lines

This commit is contained in:
Kovid Goyal 2023-03-21 11:56:23 +05:30
parent ebcf85428c
commit 2905744dad
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 94 additions and 4 deletions

View File

@ -35,6 +35,15 @@ type LogicalLine struct {
is_change_start bool is_change_start bool
} }
func (self *LogicalLine) IncrementScrollPosBy(pos *ScrollPos, amt int) (delta int) {
if len(self.screen_lines) > 0 {
npos := utils.Max(0, utils.Min(pos.screen_line+amt, len(self.screen_lines)-1))
delta = npos - pos.screen_line
pos.screen_line = npos
}
return
}
func fit_in(text string, count int) string { func fit_in(text string, count int) string {
truncated := wcswidth.TruncateToVisualLength(text, count) truncated := wcswidth.TruncateToVisualLength(text, count)
if len(truncated) >= len(text) { if len(truncated) >= len(text) {
@ -130,6 +139,57 @@ type LogicalLines struct {
margin_size, columns int margin_size, columns int
} }
func (self *LogicalLines) At(i int) *LogicalLine { return self.lines[i] }
func (self *LogicalLines) Len() int { return len(self.lines) }
func (self *LogicalLines) Minus(a, b ScrollPos) (delta int) {
// a - b
amt := 1
if a.Less(b) {
amt = -1
}
for a != b {
d := self.IncrementScrollPosBy(&a, amt)
if d == 0 {
break
}
delta += d
}
return
}
func (self *LogicalLines) IncrementScrollPosBy(pos *ScrollPos, amt int) (delta int) {
if pos.logical_line < 0 || pos.logical_line >= len(self.lines) || amt == 0 {
return
}
one := 1
if amt < 0 {
one = -1
}
for amt != 0 {
line := self.lines[pos.logical_line]
d := line.IncrementScrollPosBy(pos, amt)
if d == 0 {
nlp := pos.logical_line + one
if nlp < 0 || nlp >= len(self.lines) {
break
}
pos.logical_line = nlp
if one > 0 {
pos.screen_line = 0
} else {
pos.screen_line = len(self.lines[nlp].screen_lines) - 1
}
delta += one
amt -= one
} else {
amt -= d
delta += d
}
}
return
}
func image_lines(left_path, right_path string, columns, margin_size int, ans []*LogicalLine) ([]*LogicalLine, error) { func image_lines(left_path, right_path string, columns, margin_size int, ans []*LogicalLine) ([]*LogicalLine, error) {
// TODO: Implement this // TODO: Implement this
return ans, nil return ans, nil

View File

@ -24,6 +24,10 @@ type ScrollPos struct {
logical_line, screen_line int logical_line, screen_line int
} }
func (self ScrollPos) Less(other ScrollPos) bool {
return self.logical_line < other.logical_line || (self.logical_line == other.logical_line && self.screen_line < other.screen_line)
}
type AsyncResult struct { type AsyncResult struct {
err error err error
rtype ResultType rtype ResultType
@ -43,7 +47,7 @@ type Handler struct {
current_context_count, original_context_count int current_context_count, original_context_count int
added_count, removed_count int added_count, removed_count int
screen_size struct{ rows, columns, num_lines int } screen_size struct{ rows, columns, num_lines int }
scroll_pos ScrollPos scroll_pos, max_scroll_pos ScrollPos
} }
func (self *Handler) calculate_statistics() { func (self *Handler) calculate_statistics() {
@ -161,10 +165,26 @@ func (self *Handler) on_resize(old_size, new_size loop.ScreenSize) error {
} }
func (self *Handler) render_diff() (err error) { func (self *Handler) render_diff() (err error) {
if self.screen_size.columns < 8 {
return fmt.Errorf("Screen too narrow, need at least 8 columns")
}
if self.screen_size.rows < 2 {
return fmt.Errorf("Screen too short, need at least 2 rows")
}
self.logical_lines, err = render(self.collection, self.diff_map, self.screen_size.columns) self.logical_lines, err = render(self.collection, self.diff_map, self.screen_size.columns)
if err != nil { if err != nil {
return err return err
} }
last := self.logical_lines.Len() - 1
self.max_scroll_pos.logical_line = last
if last > -1 {
self.max_scroll_pos.screen_line = len(self.logical_lines.At(last).screen_lines) - 1
} else {
self.max_scroll_pos.screen_line = 0
}
DebugPrintln(self.max_scroll_pos)
self.logical_lines.IncrementScrollPosBy(&self.max_scroll_pos, -self.screen_size.num_lines+1)
DebugPrintln(self.max_scroll_pos)
return nil return nil
// TODO: current search see python implementation // TODO: current search see python implementation
} }
@ -210,8 +230,14 @@ func (self *Handler) on_key_event(ev *loop.KeyEvent) error {
return nil return nil
} }
func (self *Handler) scroll_lines(amt int) { func (self *Handler) scroll_lines(amt int) (delta int) {
// TODO: Implement me before := self.scroll_pos
delta = self.logical_lines.IncrementScrollPosBy(&self.scroll_pos, amt)
if delta > 0 && self.max_scroll_pos.Less(self.scroll_pos) {
self.scroll_pos = self.max_scroll_pos
delta = self.logical_lines.Minus(self.scroll_pos, before)
}
return
} }
func (self *Handler) dispatch_action(name, args string) error { func (self *Handler) dispatch_action(name, args string) error {
@ -221,7 +247,11 @@ func (self *Handler) dispatch_action(name, args string) error {
case `scroll_by`: case `scroll_by`:
amt, err := strconv.Atoi(args) amt, err := strconv.Atoi(args)
if err == nil { if err == nil {
self.scroll_lines(amt) if self.scroll_lines(amt) == 0 {
self.lp.Beep()
} else {
self.draw_screen()
}
} else { } else {
self.lp.Beep() self.lp.Beep()
} }