From 93099cca8783ac0da1352939a95822a2e7ab1bd3 Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Mon, 6 Nov 2023 08:46:18 +0900 Subject: [PATCH] Add section-header-num option If the section header number is greater than 1, the lines after the section delimiter are also treated as section headers. This is an implementation of #461. --- main.go | 8 ++++++++ oviewer/document.go | 6 ------ oviewer/draw.go | 19 +++++++++++++++---- oviewer/move_vertical.go | 6 +++--- oviewer/oviewer.go | 6 +++++- oviewer/search_move.go | 9 ++++++--- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index b1003d1c..1c1a8215 100644 --- a/main.go +++ b/main.go @@ -83,6 +83,11 @@ It supports various compressed files(gzip, bzip2, zstd, lz4, and xz). config.General.ColumnDelimiter = "\t" } + // SectionHeader is enabled if SectionHeaderNum is greater than 0. + if config.General.SectionHeaderNum > 0 { + config.General.SectionHeader = true + } + // Set a global variable to convert to a style before opening the file. oviewer.OverStrikeStyle = oviewer.ToTcellStyle(config.StyleOverStrike) oviewer.OverLineStyle = oviewer.ToTcellStyle(config.StyleOverLine) @@ -365,6 +370,9 @@ func init() { rootCmd.PersistentFlags().BoolP("section-header", "", false, "enable section-delimiter line as Header") _ = viper.BindPFlag("general.SectionHeader", rootCmd.PersistentFlags().Lookup("section-header")) + rootCmd.PersistentFlags().IntP("section-header-num", "", 1, "number of header lines") + _ = viper.BindPFlag("general.SectionHeaderNum", rootCmd.PersistentFlags().Lookup("section-header-num")) + rootCmd.PersistentFlags().BoolP("follow-mode", "f", false, "follow mode") _ = viper.BindPFlag("general.FollowMode", rootCmd.PersistentFlags().Lookup("follow-mode")) diff --git a/oviewer/document.go b/oviewer/document.go index a61439fe..849ee13b 100644 --- a/oviewer/document.go +++ b/oviewer/document.go @@ -87,8 +87,6 @@ type Document struct { // columnCursor is the number of columns. columnCursor int - // sectionHeaderNum is the number of lines in the section header. - sectionHeaderNum int // jumpTargetNum is the display position of search results. jumpTargetNum int // jumpTargetSection is the display position of search results. @@ -458,10 +456,6 @@ func (m *Document) setDelimiter(delm string) { func (m *Document) setSectionDelimiter(delm string) { m.SectionDelimiter = delm m.SectionDelimiterReg = regexpCompile(delm, true) - m.sectionHeaderNum = 0 - if m.SectionHeader && m.SectionDelimiter != "" { - m.sectionHeaderNum = 1 - } } // setMultiColorWords set multiple strings to highlight with multiple colors. diff --git a/oviewer/draw.go b/oviewer/draw.go index 2ec2ff9c..c7d4f0d5 100644 --- a/oviewer/draw.go +++ b/oviewer/draw.go @@ -40,7 +40,9 @@ func (root *Root) draw() { n := root.drawSectionHeader(lN) if lN != n { lN = n - m.topLN = lN + if m.topLN == 0 { + m.topLN = 1 + } } // Body @@ -110,6 +112,8 @@ func (root *Root) drawHeader() int { } // drawSectionHeader draws section header. +// drawSectionHeader advances the line +// if the section header contains a line in the terminal. func (root *Root) drawSectionHeader(lN int) int { m := root.Doc if !m.SectionHeader || m.SectionDelimiter == "" { @@ -134,7 +138,7 @@ func (root *Root) drawSectionHeader(lN int) int { if pn > sectionLN { sn = sectionLN line, valid := m.getLineC(sn, m.TabWidth) - for y := m.headerLen; sn < sectionLN+m.sectionHeaderNum; y++ { + for y := m.headerLen; sn < sectionLN+m.SectionHeaderNum; y++ { if root.Doc.LineNumMode { if valid { root.drawLineNumber(sn, y) @@ -142,6 +146,9 @@ func (root *Root) drawSectionHeader(lN int) int { root.blankLineNumber(y) } } + if valid { + root.styleContent(lN, line) + } sx, nextN = root.drawLine(y, sx, sn, line.lc) root.sectionLineHighlight(y, line.str) m.headerLen += 1 @@ -151,7 +158,7 @@ func (root *Root) drawSectionHeader(lN int) int { } } } - return pn + return pn + (m.SectionHeaderNum - 1) } // drawBody draws body. @@ -646,8 +653,12 @@ func (root *Root) sectionLineHighlight(y int, str string) { log.Printf("Regular expression is not set: %s", root.Doc.SectionDelimiter) return } - + if root.scr.sectionHeaderLeft > 0 { + root.yStyle(y, root.StyleSectionLine) + root.scr.sectionHeaderLeft-- + } if root.Doc.SectionDelimiterReg.MatchString(str) { root.yStyle(y, root.StyleSectionLine) + root.scr.sectionHeaderLeft = root.Doc.SectionHeaderNum - 1 } } diff --git a/oviewer/move_vertical.go b/oviewer/move_vertical.go index 18e8ee35..8d5abd39 100644 --- a/oviewer/move_vertical.go +++ b/oviewer/move_vertical.go @@ -256,7 +256,7 @@ func (m *Document) moveNextSection() error { m.movePgDn() return ErrNoDelimiter } - m.moveLine((lN - m.firstLine() + m.sectionHeaderNum) + m.SectionStartPosition) + m.moveLine((lN - m.firstLine() + m.SectionHeaderNum) + m.SectionStartPosition) return nil } @@ -277,14 +277,14 @@ func (m *Document) movePrevSection() error { return nil } - lN, err := m.prevSection(m.topLN + m.firstLine() - m.sectionHeaderNum) + lN, err := m.prevSection(m.topLN + m.firstLine() - m.SectionHeaderNum) if err != nil { m.moveTop() return err } lN = (lN - m.firstLine()) + m.SectionStartPosition lN = max(lN, m.BufStartNum()) - m.moveLine(lN + m.sectionHeaderNum) + m.moveLine(lN + m.SectionHeaderNum) return nil } diff --git a/oviewer/oviewer.go b/oviewer/oviewer.go index 78c088f8..c08dfaaa 100644 --- a/oviewer/oviewer.go +++ b/oviewer/oviewer.go @@ -94,6 +94,8 @@ type SCR struct { vHeight int // startX is the start position of x. startX int + // Process as a section header if the remaining value is 1 or more. + sectionHeaderLeft int } // LineNumber is Number of logical lines and number of wrapping lines on the screen. @@ -130,6 +132,8 @@ type general struct { MarkStyleWidth int // SectionStartPosition is a section start position. SectionStartPosition int + // SectionHeaderNum is the number of lines in the section header. + SectionHeaderNum int // HScrollWidth is the horizontal scroll width. HScrollWidth string // HScrollWidthNum is the horizontal scroll width. @@ -929,7 +933,7 @@ func (root *Root) WriteOriginal() { m.bottomLN = m.BufEndNum() } - start := max(0, m.topLN-(m.sectionHeaderNum+root.BeforeWriteOriginal)) + start := max(0, m.topLN-(m.SectionHeaderNum+root.BeforeWriteOriginal)) end := m.bottomLN - 1 if root.AfterWriteOriginal != 0 { end = m.topLN + root.AfterWriteOriginal - 1 diff --git a/oviewer/search_move.go b/oviewer/search_move.go index 36965052..9064450c 100644 --- a/oviewer/search_move.go +++ b/oviewer/search_move.go @@ -5,8 +5,11 @@ package oviewer // If the search term is off screen, move until the search term is visible. func (m *Document) searchGoTo(lN int, x int) { m.searchGoX(x) - - m.topLN = lN - m.firstLine() + sn := 0 + if lN > m.firstLine()+m.SectionHeaderNum-1 { + sn = (m.SectionHeaderNum - 1) + } + m.topLN = lN - (m.firstLine() + sn) m.moveYUp(m.jumpTargetNum) } @@ -25,7 +28,7 @@ func (m *Document) searchGoSection(lN int, x int) { sN = 0 } if m.SectionHeader { - sN = (sN - m.firstLine() + m.sectionHeaderNum) + m.SectionStartPosition + sN = (sN - m.firstLine() + m.SectionHeaderNum) + m.SectionStartPosition sN = max(sN, m.BufStartNum()) } y := 0