mirror of
https://github.com/walles/moar.git
synced 2024-09-11 12:15:43 +03:00
parent
871cf523c0
commit
b96c88c4d1
@ -1,8 +1,6 @@
|
||||
package m
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/walles/moar/twin"
|
||||
)
|
||||
|
||||
@ -13,20 +11,12 @@ func (p *Pager) Page() error {
|
||||
// Screen setup failed
|
||||
return e
|
||||
}
|
||||
defer func() {
|
||||
screen.Close()
|
||||
if p.DeInit {
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: Consider moving this logic into the twin package, or into Pager.
|
||||
_, height := p.screen.Size()
|
||||
lines := p.reader.GetLines(p.firstLineOneBased, height-1).lines
|
||||
for _, line := range lines {
|
||||
fmt.Println(line.raw)
|
||||
}
|
||||
}()
|
||||
|
||||
p.StartPaging(screen)
|
||||
return nil
|
||||
screen.Close()
|
||||
if p.DeInit {
|
||||
return nil
|
||||
}
|
||||
|
||||
return p.ReprintAfterExit()
|
||||
}
|
||||
|
15
m/pager.go
15
m/pager.go
@ -710,3 +710,18 @@ func (p *Pager) StartPaging(screen twin.Screen) {
|
||||
log.Warnf("Reader reported an error: %s", p.reader.err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// After the pager has exited and the normal screen has been restored, you can
|
||||
// call this method to print the pager contents to screen again, faking
|
||||
// "leaving" pager contents on screen after exit.
|
||||
func (p *Pager) ReprintAfterExit() error {
|
||||
// Figure out how many screen lines are used by pager contents
|
||||
_, height := p.screen.Size()
|
||||
heightWithoutFooter := height - 1
|
||||
lineCount := len(p.reader.GetLines(p.firstLineOneBased, heightWithoutFooter).lines)
|
||||
|
||||
if lineCount > 0 {
|
||||
p.screen.ShowNLines(lineCount)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
23
moar.go
23
moar.go
@ -150,6 +150,7 @@ func main() {
|
||||
"Highlighting style from https://xyproto.github.io/splash/docs/longer/all.html")
|
||||
colorsOption := flagSet.String("colors", "16M", "Highlighting palette size: 8, 16, 256, 16M")
|
||||
noLineNumbers := flagSet.Bool("no-linenumbers", false, "Hide line numbers on startup, press left arrow key to show")
|
||||
noClearOnExit := flagSet.Bool("no-clear-on-exit", false, "Retain screen contents when exiting moar")
|
||||
|
||||
// Combine flags from environment and from command line
|
||||
flags := os.Args[1:]
|
||||
@ -246,7 +247,7 @@ func main() {
|
||||
if stdinIsRedirected {
|
||||
// Display input pipe contents
|
||||
reader := m.NewReaderFromStream("", os.Stdin)
|
||||
startPaging(reader, *wrap, *noLineNumbers)
|
||||
startPaging(reader, *wrap, *noLineNumbers, *noClearOnExit)
|
||||
return
|
||||
}
|
||||
|
||||
@ -256,16 +257,21 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
startPaging(reader, *wrap, *noLineNumbers)
|
||||
startPaging(reader, *wrap, *noLineNumbers, *noClearOnExit)
|
||||
}
|
||||
|
||||
func startPaging(reader *m.Reader, wrapLongLines bool, noLineNumbers bool) {
|
||||
func startPaging(reader *m.Reader, wrapLongLines bool, noLineNumbers bool, noClearOnExit bool) {
|
||||
screen, e := twin.NewScreen()
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
|
||||
var loglines strings.Builder
|
||||
log.SetOutput(&loglines)
|
||||
pager := m.NewPager(reader)
|
||||
pager.WrapLongLines = wrapLongLines
|
||||
pager.ShowLineNumbers = !noLineNumbers
|
||||
|
||||
defer func() {
|
||||
// Restore screen...
|
||||
screen.Close()
|
||||
@ -276,6 +282,13 @@ func startPaging(reader *m.Reader, wrapLongLines bool, noLineNumbers bool) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if noClearOnExit {
|
||||
err := pager.ReprintAfterExit()
|
||||
if err != nil {
|
||||
log.Error("Failed reprinting pager view after exit", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(loglines.String()) > 0 {
|
||||
printProblemsHeader()
|
||||
|
||||
@ -286,9 +299,5 @@ func startPaging(reader *m.Reader, wrapLongLines bool, noLineNumbers bool) {
|
||||
}
|
||||
}()
|
||||
|
||||
log.SetOutput(&loglines)
|
||||
pager := m.NewPager(reader)
|
||||
pager.WrapLongLines = wrapLongLines
|
||||
pager.ShowLineNumbers = !noLineNumbers
|
||||
pager.StartPaging(screen)
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ func (screen *FakeScreen) Show() {
|
||||
// This method intentionally left blank
|
||||
}
|
||||
|
||||
func (screen *FakeScreen) ShowNLines(int) {
|
||||
// This method intentionally left blank
|
||||
}
|
||||
|
||||
func (screen *FakeScreen) Size() (int, int) {
|
||||
return screen.width, screen.height
|
||||
}
|
||||
|
@ -25,6 +25,10 @@ type Screen interface {
|
||||
// Render our contents into the terminal window
|
||||
Show()
|
||||
|
||||
// Can be called after Close()ing the screen to fake retaining its output.
|
||||
// Plain Show() is what you'd call during normal operation.
|
||||
ShowNLines(lineCountToShow int)
|
||||
|
||||
// Returns screen width and height.
|
||||
//
|
||||
// NOTE: Never cache this response! On window resizes you'll get an
|
||||
@ -444,19 +448,24 @@ func renderLine(row []Cell) (string, int) {
|
||||
return builder.String(), headerLength
|
||||
}
|
||||
|
||||
// Render our contents into the terminal window
|
||||
//
|
||||
// Note that we start by prepping everything we want to write, then write it all
|
||||
// in one go. This is to make the screen update experience as atomic and flicker
|
||||
// free as possible.
|
||||
func (screen *UnixScreen) Show() {
|
||||
_, height := screen.Size()
|
||||
screen.showNLines(height, true)
|
||||
}
|
||||
|
||||
func (screen *UnixScreen) ShowNLines(height int) {
|
||||
screen.showNLines(height, false)
|
||||
}
|
||||
|
||||
func (screen *UnixScreen) showNLines(height int, clearFirst bool) {
|
||||
var builder strings.Builder
|
||||
|
||||
// Start in the top left corner:
|
||||
// https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences
|
||||
builder.WriteString("\x1b[1;1H")
|
||||
if clearFirst {
|
||||
// Start in the top left corner:
|
||||
// https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_(Control_Sequence_Introducer)_sequences
|
||||
builder.WriteString("\x1b[1;1H")
|
||||
}
|
||||
|
||||
_, height := screen.Size()
|
||||
for row := 0; row < height; row++ {
|
||||
rendered, lineLength := renderLine(screen.cells[row])
|
||||
builder.WriteString(rendered)
|
||||
|
Loading…
Reference in New Issue
Block a user