diff --git a/go.mod b/go.mod index bd68300f..054d0ffe 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.19 require ( code.rocketnine.space/tslocum/cbind v0.1.5 github.com/atotto/clipboard v0.1.4 - github.com/fsnotify/fsnotify v1.6.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/gdamore/tcell/v2 v2.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jwalton/gchalk v1.3.0 - github.com/klauspost/compress v1.17.0 + github.com/klauspost/compress v1.17.2 github.com/mattn/go-runewidth v0.0.15 github.com/noborus/guesswidth v0.3.4 github.com/pierrec/lz4 v2.6.1+incompatible diff --git a/go.sum b/go.sum index 9a2a2efd..87c61848 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= @@ -144,8 +144,8 @@ github.com/jwalton/go-supportscolor v1.1.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2q github.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8= github.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -364,7 +364,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index 2e185607..b1003d1c 100644 --- a/main.go +++ b/main.go @@ -386,6 +386,9 @@ func init() { rootCmd.PersistentFlags().StringP("jump-target", "j", "", "jump target `[int|int%|.int|'section']`") _ = viper.BindPFlag("general.JumpTarget", rootCmd.PersistentFlags().Lookup("jump-target")) + rootCmd.PersistentFlags().StringP("hscroll-width", "", "10%", "width to scroll horizontally `[int|int%|.int]`") + _ = viper.BindPFlag("general.HScrollWidth", rootCmd.PersistentFlags().Lookup("hscroll-width")) + // Config rootCmd.PersistentFlags().BoolP("disable-mouse", "", false, "disable mouse support") _ = viper.BindPFlag("DisableMouse", rootCmd.PersistentFlags().Lookup("disable-mouse")) diff --git a/oviewer/action.go b/oviewer/action.go index 94d2514d..feb8888e 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -194,7 +194,7 @@ func (root *Root) goLine(input string) { if len(input) == 0 { return } - num := docPosition(root.Doc.BufEndNum(), input) + num := calculatePosition(root.Doc.BufEndNum(), input) str := strconv.FormatFloat(num, 'f', 1, 64) if strings.HasSuffix(str, ".0") { // Line number only. @@ -538,17 +538,17 @@ func jumpPosition(height int, str string) (int, bool) { if len(s) > 0 && s[0] == 's' { return 0, true } - num := int(math.Round(docPosition(height, s))) + num := int(math.Round(calculatePosition(height, s))) if num < 0 { return (height - 1) + num, false } return num, false } -// docPosition returns the number of lines from the top for positive -// numbers (1), dot.number for percentages (.5) = 50%, and % after -// the number for percentages (50%). -func docPosition(height int, str string) float64 { +// CalculatePosition returns the number from the length for positive +// numbers (1), returns dot.number for percentages (.5) = 50%, +// and returns the % after the number for percentages (50%). return. +func calculatePosition(length int, str string) float64 { var p float64 = 0 if strings.HasPrefix(str, ".") { str = strings.TrimLeft(str, ".") @@ -568,7 +568,7 @@ func docPosition(height int, str string) float64 { } if p != 0 { - return float64(height) * p + return float64(length) * p } num, err := strconv.ParseFloat(str, 64) diff --git a/oviewer/action_test.go b/oviewer/action_test.go index 5dfe6ba8..8a114151 100644 --- a/oviewer/action_test.go +++ b/oviewer/action_test.go @@ -171,7 +171,7 @@ func Test_position(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - if got := docPosition(tt.args.height, tt.args.str); got != tt.want { + if got := calculatePosition(tt.args.height, tt.args.str); got != tt.want { t.Errorf("position() = %v, want %v", got, tt.want) } }) diff --git a/oviewer/help.go b/oviewer/help.go index 5f8b0077..0c3d974d 100644 --- a/oviewer/help.go +++ b/oviewer/help.go @@ -25,6 +25,7 @@ func NewHelp(k KeyBind) (*Document, error) { m.store.eof = 1 m.preventReload = true m.seekable = false + m.SectionHeader = true m.setSectionDelimiter("\t") atomic.StoreInt32(&m.closed, 1) if err := m.ControlReader(helpStr, nil); err != nil { diff --git a/oviewer/keybind.go b/oviewer/keybind.go index 9d2849e3..d1c99fb7 100644 --- a/oviewer/keybind.go +++ b/oviewer/keybind.go @@ -32,6 +32,8 @@ const ( actionMoveDown = "down" actionMoveUp = "up" actionMoveTop = "top" + actionMoveWidthLeft = "width_left" + actionMoveWidthRight = "width_right" actionMoveLeft = "left" actionMoveRight = "right" actionMoveHfLeft = "half_left" @@ -114,6 +116,8 @@ func (root *Root) handlers() map[string]func() { actionMovePgDn: root.movePgDn, actionMoveHfUp: root.moveHfUp, actionMoveHfDn: root.moveHfDn, + actionMoveWidthLeft: root.moveWidthLeft, + actionMoveWidthRight: root.moveWidthRight, actionMoveLeft: root.moveLeftOne, actionMoveRight: root.moveRightOne, actionMoveHfLeft: root.moveHfLeft, @@ -194,6 +198,8 @@ func defaultKeyBinds() KeyBind { actionMovePgDn: {"PageDown", "ctrl+v"}, actionMoveHfUp: {"ctrl+u"}, actionMoveHfDn: {"ctrl+d"}, + actionMoveWidthLeft: {"ctrl+shift+left"}, + actionMoveWidthRight: {"ctrl+shift+right"}, actionMoveLeft: {"left"}, actionMoveRight: {"right"}, actionMoveHfLeft: {"ctrl+left"}, @@ -277,6 +283,8 @@ func (k KeyBind) String() string { k.writeKeyBind(&b, actionMoveRight, "scroll to right") k.writeKeyBind(&b, actionMoveHfLeft, "scroll left half screen") k.writeKeyBind(&b, actionMoveHfRight, "scroll right half screen") + k.writeKeyBind(&b, actionMoveWidthLeft, "scroll left specified width") + k.writeKeyBind(&b, actionMoveWidthRight, "scroll right specified width") k.writeKeyBind(&b, actionMoveBeginLeft, "go to beginning of line") k.writeKeyBind(&b, actionMoveEndRight, "go to end of line") k.writeKeyBind(&b, actionGoLine, "go to line(input number or `.n` or `n%` allowed)") diff --git a/oviewer/mouse.go b/oviewer/mouse.go index 6107789e..87934e6e 100644 --- a/oviewer/mouse.go +++ b/oviewer/mouse.go @@ -74,7 +74,7 @@ func (root *Root) wheelRight() { if root.Doc.ColumnMode { root.moveRightOne() } else { - root.moveRight(4) + root.moveRight(root.Doc.HScrollWidthNum) } } @@ -83,7 +83,7 @@ func (root *Root) wheelLeft() { if root.Doc.ColumnMode { root.moveLeftOne() } else { - root.moveLeft(4) + root.moveLeft(root.Doc.HScrollWidthNum) } } diff --git a/oviewer/move.go b/oviewer/move.go index 12b81610..b58690e1 100644 --- a/oviewer/move.go +++ b/oviewer/move.go @@ -157,13 +157,25 @@ func (root *Root) moveRightOne() { root.moveRight(1) } +// Move to the width of the screen to the left. +// Called from a EventKey. +func (root *Root) moveWidthLeft() { + root.moveLeft(root.Doc.HScrollWidthNum) +} + +// Move to the width of the screen to the right. +// Called from a EventKey. +func (root *Root) moveWidthRight() { + root.moveRight(root.Doc.HScrollWidthNum) +} + // Move left by n amount. func (root *Root) moveLeft(n int) { root.resetSelect() defer root.releaseEventBuffer() if root.Doc.ColumnMode { - root.moveColumnLeft(n) + root.moveColumnLeft(1) return } root.moveNormalLeft(n) @@ -175,7 +187,7 @@ func (root *Root) moveRight(n int) { defer root.releaseEventBuffer() if root.Doc.ColumnMode { - root.moveColumnRight(n) + root.moveColumnRight(1) return } root.moveNormalRight(n) diff --git a/oviewer/oviewer.go b/oviewer/oviewer.go index 50fcdadf..44e4617e 100644 --- a/oviewer/oviewer.go +++ b/oviewer/oviewer.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log" + "math" "os" "os/signal" "path/filepath" @@ -129,6 +130,10 @@ type general struct { MarkStyleWidth int // SectionStartPosition is a section start position. SectionStartPosition int + // HScrollWidth is the horizontal scroll width. + HScrollWidth string + // HScrollWidthNum is the horizontal scroll width. + HScrollWidthNum int // AlternateRows alternately style rows. AlternateRows bool // ColumnMode is column mode. @@ -866,6 +871,9 @@ func mergeGeneral(src general, dst general) general { if dst.JumpTarget != "" { src.JumpTarget = dst.JumpTarget } + if dst.HScrollWidth != "" { + src.HScrollWidth = dst.HScrollWidth + } if len(dst.MultiColorWords) > 0 { src.MultiColorWords = dst.MultiColorWords } @@ -880,6 +888,8 @@ func (root *Root) prepareView() { // Do not allow size 0. root.scr.vWidth = max(root.scr.vWidth, 1) root.scr.vHeight = max(root.scr.vHeight, 1) + num := int(math.Round(calculatePosition(root.scr.vWidth, root.Doc.HScrollWidth))) + root.Doc.HScrollWidthNum = max(num, 1) root.scr.numbers = make([]LineNumber, root.scr.vHeight+1) root.Doc.statusPos = root.scr.vHeight - statusLine }