Skip to content
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

WIP: Add support for vertical header #679

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,12 @@ func init() {
return []string{"1"}, cobra.ShellCompDirectiveNoFileComp
})

rootCmd.PersistentFlags().IntP("vertical-header", "V", 0, "number of vertical header lines to be displayed constantly")
_ = viper.BindPFlag("general.VerticalHeader", rootCmd.PersistentFlags().Lookup("vertical-header"))
_ = rootCmd.RegisterFlagCompletionFunc("vertical-header", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"1"}, cobra.ShellCompDirectiveNoFileComp
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you explain me this pattern?

The field is an integer, and so here you tell viper to complete the field will the value 1, why 1? Why not []string{}

Is it a way to complete with something that will help user to understand it's a number that is expected?

I had already looked at the code and I was surprised to see this

Here you are doing it again, either on purpose or by copy pasting code.

Copy link
Owner Author

Choose a reason for hiding this comment

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

This is still a temporary option, so it doesn't make much sense.
This indicates that an option argument requires numerical values ​​(1 or more).
I thought that the blank ("") wouldn't know what to specify.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'll have to make my own test because it looks strange to me

})

rootCmd.PersistentFlags().IntP("skip-lines", "", 0, "skip the number of lines")
_ = viper.BindPFlag("general.SkipLines", rootCmd.PersistentFlags().Lookup("skip-lines"))
_ = rootCmd.RegisterFlagCompletionFunc("skip-lines", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
Expand Down
3 changes: 3 additions & 0 deletions oviewer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ func NewConfig() Config {
StyleSectionLine: OVStyle{
Background: "slateblue",
},
StyleVerticalHeader: OVStyle{
Reverse: true,
},
StyleMultiColorHighlight: []OVStyle{
{Foreground: "red"},
{Foreground: "aqua"},
Expand Down
3 changes: 3 additions & 0 deletions oviewer/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ type Document struct {
width int
// height is the height of the screen.
height int
// endExclude is the number of lines to exclude from the end.
endExclude int

// markedPoint is the position of the marked line.
markedPoint int

Expand Down
55 changes: 43 additions & 12 deletions oviewer/draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ func (root *Root) draw(ctx context.Context) {
root.prepareDraw(ctx)

// Body.
lX := m.topLX
lX := root.scr.verticalHeader
lN := m.topLN + root.scr.headerEnd
// If WrapMode is off, lX is always 0.
if !m.WrapMode {
lX = 0

// If WrapMode is enabled, the drawing position is adjusted.
if m.WrapMode {
lX += m.topLX
}
lX, lN = root.drawBody(lX, lN)
m.bottomLX = lX
Expand Down Expand Up @@ -77,6 +78,7 @@ func (root *Root) drawBody(lX int, lN int) (int, int) {
wrapNum++
if nextLX == 0 {
wrapNum = 0
nextLX = root.scr.verticalHeader
}

lX = nextLX
Expand All @@ -91,7 +93,7 @@ func (root *Root) drawHeader() {

// wrapNum is the number of wrapped lines.
wrapNum := 0
lX := 0
lX := root.scr.verticalHeader
lN := root.scr.headerLN
for y := 0; y < m.headerHeight && lN < root.scr.headerEnd; y++ {
lineC, ok := root.scr.lines[lN]
Expand All @@ -118,7 +120,7 @@ func (root *Root) drawSectionHeader() {
m := root.Doc

wrapNum := 0
lX := 0
lX := root.scr.verticalHeader
lN := root.scr.sectionHeaderLN
for y := m.headerHeight; y < m.headerHeight+m.sectionHeaderHeight && lN < root.scr.sectionHeaderEnd; y++ {
lineC, ok := root.scr.lines[lN]
Expand All @@ -142,6 +144,7 @@ func (root *Root) drawSectionHeader() {
wrapNum++
if nextLX == 0 {
wrapNum = 0
nextLX = root.scr.verticalHeader
}

lX = nextLX
Expand All @@ -151,11 +154,40 @@ func (root *Root) drawSectionHeader() {

// drawWrapLine wraps and draws the contents and returns the next drawing position.
func (root *Root) drawLine(y int, lX int, lN int, lineC LineC) (int, int) {
if root.scr.verticalHeader > 0 {
root.drawVerticalHeader(y, lX, lineC)
}
if root.Doc.WrapMode {
return root.drawWrapLine(y, lX, lN, lineC)
}

return root.drawNoWrapLine(y, root.Doc.x, lN, lineC)
return root.drawNoWrapLine(y, root.scr.verticalHeader+root.Doc.x, lN, lineC)
}

// drawVerticalHeader draws the vertical header.
func (root *Root) drawVerticalHeader(y int, lX int, lineC LineC) {
numberWidth := root.scr.numberWidth
if numberWidth > 0 {
numberWidth++
}
screen := root.Screen
for n := 0; n < root.scr.verticalHeader; n++ {
x := numberWidth + n
if lX > root.scr.verticalHeader || n >= len(lineC.lc) {
// EOL
style := lineC.eolStyle
if lineC.valid {
style = style.Reverse(true)
}
root.clearEOL(x, y, style)
break
}
c := lineC.lc[n]
if lineC.valid {
c.style = applyStyle(defaultStyle, root.StyleVerticalHeader)
}
screen.SetContent(x, y, c.mainc, c.combc, c.style)
}
}

// drawWrapLine wraps and draws the contents and returns the next drawing position.
Expand All @@ -171,7 +203,7 @@ func (root *Root) drawWrapLine(y int, lX int, lN int, lineC LineC) (int, int) {
if lX+n >= len(lineC.lc) {
// EOL
root.clearEOL(x, y, lineC.eolStyle)
lX = 0
lX = root.scr.verticalHeader
lN++
break
}
Expand Down Expand Up @@ -208,8 +240,7 @@ func (root *Root) drawNoWrapLine(y int, lX int, lN int, lineC LineC) (int, int)
screen.SetContent(x, y, c.mainc, c.combc, c.style)
}
lN++

return lX, lN
return 0, lN
}

// blankLineNumber should be blank for the line number.
Expand All @@ -220,7 +251,7 @@ func (root *Root) blankLineNumber(y int) {
if root.scr.startX <= 0 {
return
}
numC := StrToContents(strings.Repeat(" ", root.scr.startX-1), root.Doc.TabWidth)
numC := StrToContents(strings.Repeat(" ", root.scr.numberWidth), root.Doc.TabWidth)
root.setContentString(0, y, numC)
}

Expand Down Expand Up @@ -248,7 +279,7 @@ func (root *Root) drawLineNumber(lN int, y int, valid bool) {
number = number - m.firstLine() + 1

// Line numbers start at 1 except for skip and header lines.
numC := StrToContents(fmt.Sprintf("%*d", root.scr.startX-1, number), m.TabWidth)
numC := StrToContents(fmt.Sprintf("%*d", root.scr.numberWidth, number), m.TabWidth)
for i := 0; i < len(numC); i++ {
numC[i].style = applyStyle(defaultStyle, root.StyleLineNumber)
}
Expand Down
9 changes: 9 additions & 0 deletions oviewer/move_vertical.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,18 @@ func (m *Document) leftMostX(lN int) []int {
if err != nil {
return nil
}
lc = excludeRange(lc, m.endExclude)
return leftX(m.width, lc)
}

// excludeRange returns a new slice with the elements from start to end excluded.
func excludeRange(lc contents, end int) []content {
if end > len(lc) {
return []content{}
}
return lc[end:]
}

// leftX returns a list of left - most x positions when wrapping.
func leftX(width int, lc contents) []int {
if width <= 0 {
Expand Down
10 changes: 10 additions & 0 deletions oviewer/oviewer.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ type SCR struct {
// sectionHeaderEnd is the end of the section header.
sectionHeaderEnd int

// numWidth is the width of the number.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is so bad, haha

I hope it's an AI generated one 🤞

I'm sure something better than this could be suggested

numberWidth int
// verticalHeader is the width of the vertical header.
verticalHeader int

// x1, y1, x2, y2 are the coordinates selected by the mouse.
x1 int
y1 int
Expand Down Expand Up @@ -147,6 +152,8 @@ type general struct {
TabWidth int
// Header is number of header lines to be fixed.
Header int
// VerticalHeader is the number of vertical header lines.
VerticalHeader int
// SkipLines is the rows to skip.
SkipLines int
// WatchInterval is the watch interval (seconds).
Expand Down Expand Up @@ -246,6 +253,9 @@ type Config struct {
StyleOverStrike OVStyle
// StyleOverLine is a style that applies to overstrike underlines.
StyleOverLine OVStyle
// StyleVerticalHeader is a style that applies to the vertical header.
StyleVerticalHeader OVStyle

// General represents the general behavior.
General general
// BeforeWriteOriginal specifies the number of lines before the current position.
Expand Down
9 changes: 6 additions & 3 deletions oviewer/prepare_draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,20 @@ func (root *Root) prepareScreen() {

// prepareStartX prepares the start position of the x.
func (root *Root) prepareStartX() {
root.scr.startX = 0
root.scr.verticalHeader = root.General.VerticalHeader
root.scr.numberWidth = 0
root.scr.startX = root.scr.verticalHeader
m := root.Doc
m.endExclude = root.scr.verticalHeader
if !m.LineNumMode {
return
}

if m.parent != nil {
m = m.parent
}
root.scr.startX = len(strconv.Itoa(m.BufEndNum())) + 1
root.scr.numberWidth = len(strconv.Itoa(m.BufEndNum()))
root.scr.startX = root.scr.verticalHeader + root.scr.numberWidth + 1
}

// ViewSync redraws the whole thing.
Expand All @@ -73,7 +77,6 @@ func (root *Root) prepareDraw(ctx context.Context) {
root.scr.headerEnd = root.Doc.firstLine()
// Set the header height.
root.Doc.headerHeight = root.Doc.getHeight(root.scr.headerLN, root.scr.headerEnd)

// Section header.
root.scr.sectionHeaderLN = -1
root.scr.sectionHeaderEnd = 0
Expand Down
Loading