mirror of
https://github.com/walles/moar.git
synced 2024-11-23 05:53:18 +03:00
commit
98b83c45d6
5
go.mod
5
go.mod
@ -5,7 +5,10 @@ go 1.20
|
||||
require (
|
||||
github.com/alecthomas/chroma/v2 v2.12.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/klauspost/compress v1.17.4
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/ulikunitz/xz v0.5.11
|
||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc
|
||||
golang.org/x/sys v0.1.0
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
|
||||
gotest.tools/v3 v3.3.0
|
||||
@ -13,7 +16,5 @@ require (
|
||||
|
||||
require (
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -28,6 +28,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
|
||||
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
12
m/pager.go
12
m/pager.go
@ -97,6 +97,11 @@ type Pager struct {
|
||||
|
||||
// Length of the longest line displayed. This is used for limiting scrolling to the right.
|
||||
longestLineLength int
|
||||
|
||||
// Bookmarks that you can come back to.
|
||||
//
|
||||
// Ref: https://github.com/walles/moar/issues/175
|
||||
marks map[rune]scrollPosition
|
||||
}
|
||||
|
||||
type _PreHelpState struct {
|
||||
@ -122,12 +127,14 @@ Moving around
|
||||
* Arrow keys
|
||||
* Alt key plus left / right arrow steps one column at a time
|
||||
* Left / right can be used to hide / show line numbers
|
||||
* Home and End for start / end of the document
|
||||
* 'g' for going to a specific line number
|
||||
* 'm' sets a mark, you will be asked for a letter to label it with
|
||||
* ' (single quote) jumps to the mark
|
||||
* CTRL-p moves to the previous line
|
||||
* CTRL-n moves to the next line
|
||||
* 'g' for going to a specific line number
|
||||
* PageUp / 'b' and PageDown / 'f'
|
||||
* SPACE moves down a page
|
||||
* Home and End for start / end of the document
|
||||
* < / 'gg' to go to the start of the document
|
||||
* > / 'G' to go to the end of the document
|
||||
* 'h', 'l' for left and right (as in vim)
|
||||
@ -309,6 +316,7 @@ func (p *Pager) StartPaging(screen twin.Screen, chromaStyle *chroma.Style, chrom
|
||||
p.screen = screen
|
||||
p.linePrefix = getLineColorPrefix(chromaStyle, chromaFormatter)
|
||||
p.mode = PagerModeViewing{pager: p}
|
||||
p.marks = make(map[rune]scrollPosition)
|
||||
|
||||
go func() {
|
||||
for range p.reader.moreLinesAdded {
|
||||
|
84
m/pagermode-jump-to-mark.go
Normal file
84
m/pagermode-jump-to-mark.go
Normal file
@ -0,0 +1,84 @@
|
||||
package m
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/walles/moar/twin"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
type PagerModeJumpToMark struct {
|
||||
pager *Pager
|
||||
}
|
||||
|
||||
func (m PagerModeJumpToMark) drawFooter(_ string, _ string) {
|
||||
p := m.pager
|
||||
|
||||
_, height := p.screen.Size()
|
||||
|
||||
pos := 0
|
||||
for _, token := range m.getMarkPrompt() {
|
||||
p.screen.SetCell(pos, height-1, twin.NewCell(token, twin.StyleDefault))
|
||||
pos++
|
||||
}
|
||||
}
|
||||
|
||||
func (m PagerModeJumpToMark) getMarkPrompt() string {
|
||||
// Special case having zero, one or multiple marks
|
||||
if len(m.pager.marks) == 0 {
|
||||
return "No marks set, press 'm' to set one!"
|
||||
}
|
||||
|
||||
if len(m.pager.marks) == 1 {
|
||||
for key := range m.pager.marks {
|
||||
return "Jump to your mark: " + string(key)
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple marks, list them
|
||||
marks := maps.Keys(m.pager.marks)
|
||||
sort.Slice(marks, func(i, j int) bool {
|
||||
return marks[i] < marks[j]
|
||||
})
|
||||
|
||||
prompt := "Jump to one of these marks: "
|
||||
for i, mark := range marks {
|
||||
if i > 0 {
|
||||
prompt += ", "
|
||||
}
|
||||
prompt += string(mark)
|
||||
}
|
||||
|
||||
return prompt
|
||||
}
|
||||
|
||||
func (m PagerModeJumpToMark) onKey(key twin.KeyCode) {
|
||||
p := m.pager
|
||||
|
||||
switch key {
|
||||
case twin.KeyEnter, twin.KeyEscape:
|
||||
// Never mind I
|
||||
p.mode = PagerModeViewing{pager: p}
|
||||
|
||||
default:
|
||||
// Never mind II
|
||||
p.mode = PagerModeViewing{pager: p}
|
||||
p.mode.onKey(key)
|
||||
}
|
||||
}
|
||||
|
||||
func (m PagerModeJumpToMark) onRune(char rune) {
|
||||
if len(m.pager.marks) == 0 && char == 'm' {
|
||||
//nolint:gosimple // The linter's advice is just wrong here
|
||||
m.pager.mode = PagerModeMark{pager: m.pager}
|
||||
return
|
||||
}
|
||||
|
||||
destination, ok := m.pager.marks[char]
|
||||
if ok {
|
||||
m.pager.scrollPosition = destination
|
||||
}
|
||||
|
||||
//nolint:gosimple // The linter's advice is just wrong here
|
||||
m.pager.mode = PagerModeViewing{pager: m.pager}
|
||||
}
|
44
m/pagermode-mark.go
Normal file
44
m/pagermode-mark.go
Normal file
@ -0,0 +1,44 @@
|
||||
package m
|
||||
|
||||
import "github.com/walles/moar/twin"
|
||||
|
||||
type PagerModeMark struct {
|
||||
pager *Pager
|
||||
}
|
||||
|
||||
func (m PagerModeMark) drawFooter(_ string, _ string) {
|
||||
p := m.pager
|
||||
|
||||
_, height := p.screen.Size()
|
||||
|
||||
pos := 0
|
||||
for _, token := range "Press any key to label your mark: " {
|
||||
p.screen.SetCell(pos, height-1, twin.NewCell(token, twin.StyleDefault))
|
||||
pos++
|
||||
}
|
||||
|
||||
// Add a cursor
|
||||
p.screen.SetCell(pos, height-1, twin.NewCell(' ', twin.StyleDefault.WithAttr(twin.AttrReverse)))
|
||||
}
|
||||
|
||||
func (m PagerModeMark) onKey(key twin.KeyCode) {
|
||||
p := m.pager
|
||||
|
||||
switch key {
|
||||
case twin.KeyEnter, twin.KeyEscape:
|
||||
// Never mind I
|
||||
p.mode = PagerModeViewing{pager: p}
|
||||
|
||||
default:
|
||||
// Never mind II
|
||||
p.mode = PagerModeViewing{pager: p}
|
||||
p.mode.onKey(key)
|
||||
}
|
||||
}
|
||||
|
||||
func (m PagerModeMark) onRune(char rune) {
|
||||
m.pager.marks[char] = m.pager.scrollPosition
|
||||
|
||||
//nolint:gosimple // The linter's advice is just wrong here
|
||||
m.pager.mode = PagerModeViewing{pager: m.pager}
|
||||
}
|
@ -162,6 +162,14 @@ func (m PagerModeViewing) onRune(char rune) {
|
||||
case 'p', 'N':
|
||||
p.scrollToPreviousSearchHit()
|
||||
|
||||
case 'm':
|
||||
p.mode = PagerModeMark{pager: p}
|
||||
p.TargetLineNumber = nil
|
||||
|
||||
case '\'':
|
||||
p.mode = PagerModeJumpToMark{pager: p}
|
||||
p.TargetLineNumber = nil
|
||||
|
||||
case 'w':
|
||||
p.WrapLongLines = !p.WrapLongLines
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user