mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-05-13 08:26:56 +00:00
kitten diff: add support for sticky header
This commit is contained in:
parent
2af98fd4fd
commit
7729e6e1ae
3 changed files with 50 additions and 2 deletions
|
|
@ -89,6 +89,11 @@ If an invalid expression is provided, diff will fail with an error.
|
|||
'''
|
||||
)
|
||||
|
||||
opt('sticky_header', 'no', option_type='to_bool', long_text='''
|
||||
When scrolled past the header of a file, keep the file's name and separator
|
||||
pinned to the top of the screen.
|
||||
''')
|
||||
|
||||
egr() # }}}
|
||||
|
||||
# colors {{{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -318,11 +319,24 @@ func title_lines(left_path, right_path string, columns, margin_size int, ans []*
|
|||
|
||||
type LogicalLines struct {
|
||||
lines []*LogicalLine
|
||||
title_line_indices []int // sorted indices of TITLE_LINEs in lines -- used for sticky_header
|
||||
margin_size, columns int
|
||||
}
|
||||
|
||||
func (self *LogicalLines) At(i int) *LogicalLine { return self.lines[i] }
|
||||
|
||||
func (self *LogicalLines) TitleLineIdxFor(line_idx int) int {
|
||||
if len(self.title_line_indices) == 0 || line_idx < 0 {
|
||||
return -1
|
||||
}
|
||||
// first title index > line_idx, so the one before it is our answer
|
||||
i := sort.SearchInts(self.title_line_indices, line_idx+1)
|
||||
if i == 0 {
|
||||
return -1
|
||||
}
|
||||
return self.title_line_indices[i-1]
|
||||
}
|
||||
|
||||
func (self *LogicalLines) ScreenLineAt(pos ScrollPos) *ScreenLine {
|
||||
if pos.logical_line < len(self.lines) && pos.logical_line >= 0 {
|
||||
line := self.lines[pos.logical_line]
|
||||
|
|
@ -793,8 +807,13 @@ func rename_lines(path, other_path string, columns, margin_size int, ans []*Logi
|
|||
func render(collection *Collection, diff_map map[string]*Patch, screen_size screen_size, largest_line_number int, image_size graphics.Size) (result *LogicalLines, err error) {
|
||||
margin_size := utils.Max(3, len(strconv.Itoa(largest_line_number))+1)
|
||||
ans := make([]*LogicalLine, 0, 1024)
|
||||
var title_line_indices []int
|
||||
track_titles := conf != nil && conf.Sticky_header
|
||||
columns := screen_size.columns
|
||||
err = collection.Apply(func(path, item_type, changed_path string) error {
|
||||
if track_titles {
|
||||
title_line_indices = append(title_line_indices, len(ans))
|
||||
}
|
||||
ans = title_lines(path, changed_path, columns, margin_size, ans)
|
||||
defer func() {
|
||||
ans = append(ans, &LogicalLine{line_type: EMPTY_LINE, screen_lines: []*ScreenLine{{}}})
|
||||
|
|
@ -863,5 +882,5 @@ func render(collection *Collection, diff_map map[string]*Patch, screen_size scre
|
|||
// Having am empty list of lines causes panics later on
|
||||
ll = []*LogicalLine{{line_type: EMPTY_LINE, screen_lines: []*ScreenLine{{}}}}
|
||||
}
|
||||
return &LogicalLines{lines: ll, margin_size: margin_size, columns: columns}, err
|
||||
return &LogicalLines{lines: ll, title_line_indices: title_line_indices, margin_size: margin_size, columns: columns}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,7 +414,11 @@ func (self *Handler) draw_screen() {
|
|||
}
|
||||
pos := self.scroll_pos
|
||||
seen_images := utils.NewSet[int]()
|
||||
for num_written := 0; num_written < self.screen_size.num_lines; num_written++ {
|
||||
num_written := 0
|
||||
if conf != nil && conf.Sticky_header {
|
||||
num_written = self.draw_sticky_header(&pos)
|
||||
}
|
||||
for ; num_written < self.screen_size.num_lines; num_written++ {
|
||||
ll := self.logical_lines.At(pos.logical_line)
|
||||
if ll == nil || self.logical_lines.ScreenLineAt(pos) == nil {
|
||||
num_written--
|
||||
|
|
@ -443,6 +447,26 @@ func (self *Handler) draw_screen() {
|
|||
self.draw_status_line()
|
||||
}
|
||||
|
||||
func (self *Handler) draw_sticky_header(pos *ScrollPos) int {
|
||||
title_idx := self.logical_lines.TitleLineIdxFor(pos.logical_line)
|
||||
if title_idx < 0 {
|
||||
return 0
|
||||
}
|
||||
// file title
|
||||
self.logical_lines.At(title_idx).render_screen_line(0, self.lp, self.logical_lines.margin_size, self.logical_lines.columns)
|
||||
self.lp.MoveCursorVertically(1)
|
||||
self.lp.QueueWriteString("\x1b[m\r")
|
||||
self.logical_lines.IncrementScrollPosBy(pos, 1)
|
||||
|
||||
// separator
|
||||
self.logical_lines.At(title_idx+1).render_screen_line(0, self.lp, self.logical_lines.margin_size, self.logical_lines.columns)
|
||||
self.lp.MoveCursorVertically(1)
|
||||
self.lp.QueueWriteString("\x1b[m\r")
|
||||
self.logical_lines.IncrementScrollPosBy(pos, 1)
|
||||
|
||||
return 2
|
||||
}
|
||||
|
||||
func (self *Handler) draw_status_line() {
|
||||
if self.logical_lines == nil || self.diff_map == nil {
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue