1
1
mirror of https://github.com/walles/moar.git synced 2024-09-11 12:15:43 +03:00

Merge branch 'johan/follow'

Fixes #108
This commit is contained in:
Johan Walles 2022-11-26 22:29:44 +01:00
commit 1b0a214bb3
4 changed files with 45 additions and 6 deletions

View File

@ -30,6 +30,7 @@ Doing the right thing includes:
- The position in the file is always shown
- Supports **word wrapping** (on actual word boundaries) if requested using
`--wrap` or by pressing <kbd>w</kbd>
- **Follows output** as long as you are on the last line, just like `tail -f`
[For compatibility reasons](https://github.com/walles/moar/issues/14), `moar`
uses the formats declared in these environment variables when viewing man pages:

View File

@ -55,6 +55,7 @@ type Pager struct {
searchString string
searchPattern *regexp.Regexp
gotoLineString string
Following bool
isShowingHelp bool
preHelpState *_PreHelpState
@ -82,6 +83,7 @@ type _PreHelpState struct {
reader *Reader
scrollPosition scrollPosition
leftColumnZeroBased int
following bool
}
const _EofMarkerFormat = "\x1b[7m" // Reverse video
@ -133,6 +135,10 @@ Source Code
Available at https://github.com/walles/moar/.
`)
func (pm _PagerMode) isViewing() bool {
return pm == _Viewing || pm == _NotFound
}
// NewPager creates a new Pager
func NewPager(r *Reader) *Pager {
var name string
@ -189,6 +195,7 @@ func (p *Pager) Quit() {
p.reader = p.preHelpState.reader
p.scrollPosition = p.preHelpState.scrollPosition
p.leftColumnZeroBased = p.preHelpState.leftColumnZeroBased
p.Following = p.preHelpState.following
p.preHelpState = nil
}
@ -211,6 +218,14 @@ func (p *Pager) moveRight(delta int) {
}
}
func (p *Pager) handleScrolledUp() {
p.Following = false
}
func (p *Pager) handleScrolledDown() {
p.Following = p.isScrolledToEnd()
}
func (p *Pager) onKey(keyCode twin.KeyCode) {
if p.mode == _Searching {
p.onSearchKey(keyCode)
@ -234,10 +249,12 @@ func (p *Pager) onKey(keyCode twin.KeyCode) {
case twin.KeyUp:
// Clipping is done in _Redraw()
p.scrollPosition = p.scrollPosition.PreviousLine(1)
p.handleScrolledUp()
case twin.KeyDown, twin.KeyEnter:
// Clipping is done in _Redraw()
p.scrollPosition = p.scrollPosition.NextLine(1)
p.handleScrolledDown()
case twin.KeyRight:
p.moveRight(16)
@ -247,17 +264,20 @@ func (p *Pager) onKey(keyCode twin.KeyCode) {
case twin.KeyHome:
p.scrollPosition = newScrollPosition("Pager scroll position")
p.handleScrolledUp()
case twin.KeyEnd:
p.scrollToEnd()
case twin.KeyPgDown:
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.NextLine(height - 1)
case twin.KeyPgUp:
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.PreviousLine(height - 1)
p.handleScrolledUp()
case twin.KeyPgDown:
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.NextLine(height - 1)
p.handleScrolledDown()
default:
log.Debugf("Unhandled key event %v", keyCode)
@ -287,10 +307,12 @@ func (p *Pager) onRune(char rune) {
reader: p.reader,
scrollPosition: p.scrollPosition,
leftColumnZeroBased: p.leftColumnZeroBased,
following: p.Following,
}
p.reader = _HelpReader
p.scrollPosition = newScrollPosition("Pager scroll position")
p.leftColumnZeroBased = 0
p.Following = false
p.isShowingHelp = true
}
@ -300,10 +322,12 @@ func (p *Pager) onRune(char rune) {
case 'k', 'y':
// Clipping is done in _Redraw()
p.scrollPosition = p.scrollPosition.PreviousLine(1)
p.handleScrolledUp()
case 'j', 'e':
// Clipping is done in _Redraw()
p.scrollPosition = p.scrollPosition.NextLine(1)
p.handleScrolledDown()
case 'l':
// vim right
@ -315,6 +339,7 @@ func (p *Pager) onRune(char rune) {
case '<':
p.scrollPosition = newScrollPosition("Pager scroll position")
p.handleScrolledUp()
case '>', 'G':
p.scrollToEnd()
@ -322,22 +347,26 @@ func (p *Pager) onRune(char rune) {
case 'f', ' ':
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.NextLine(height - 1)
p.handleScrolledDown()
case 'b':
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.PreviousLine(height - 1)
p.handleScrolledUp()
// '\x15' = CTRL-u, should work like just 'u'.
// Ref: https://github.com/walles/moar/issues/90
case 'u', '\x15':
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.PreviousLine(height / 2)
p.handleScrolledUp()
// '\x04' = CTRL-d, should work like just 'd'.
// Ref: https://github.com/walles/moar/issues/90
case 'd', '\x04':
_, height := p.screen.Size()
p.scrollPosition = p.scrollPosition.NextLine(height / 2)
p.handleScrolledDown()
case '/':
p.mode = _Searching
@ -458,8 +487,9 @@ func (p *Pager) StartPaging(screen twin.Screen) {
// We'll be implicitly redrawn just by taking another lap in the loop
case eventMoreLinesAvailable:
// Doing nothing here is fine; screen will be refreshed on the next
// iteration of the main loop.
if p.mode.isViewing() && p.Following {
p.scrollToEnd()
}
case eventSpinnerUpdate:
spinner = event.spinner

View File

@ -277,6 +277,8 @@ func (p *Pager) scrollToEnd() {
// Scroll down enough. We know for sure the last line won't wrap into more
// lines than the number of characters it contains.
p.scrollPosition.internalDontTouch.deltaScreenLines = len(lastInputLine.raw)
p.Following = true
}
// Can be either because Pager.scrollToEnd() was just called or because the user

View File

@ -115,6 +115,9 @@ func (p *Pager) scrollToNextSearchHit() {
return
}
p.scrollPosition = *firstHitPosition
// Don't let any search hit scroll out of sight
p.Following = false
}
func (p *Pager) scrollToPreviousSearchHit() {
@ -150,6 +153,9 @@ func (p *Pager) scrollToPreviousSearchHit() {
return
}
p.scrollPosition = *firstHitPosition
// Don't let any search hit scroll out of sight
p.Following = false
}
func (p *Pager) updateSearchPattern() {