mirror of
https://github.com/walles/moar.git
synced 2024-08-16 23:40:35 +03:00
Show file name and line numbers
This commit is contained in:
parent
007112e896
commit
70500056af
3
go.mod
3
go.mod
@ -4,5 +4,8 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/gdamore/tcell v1.1.2
|
||||
github.com/google/go-cmp v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
|
||||
gotest.tools v2.2.0+incompatible
|
||||
)
|
||||
|
6
go.sum
6
go.sum
@ -3,10 +3,14 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.1.2 h1:Afe8cU6SECC06UmvaJ55Jr3Eh0tz/ywLjqWYqjGZp3s=
|
||||
github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8uzurE=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@ -18,3 +22,5 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
|
@ -50,7 +50,7 @@ func (p *_Pager) _AddLines(logger *log.Logger) {
|
||||
|
||||
pos := 0
|
||||
footerStyle := tcell.StyleDefault.Reverse(true)
|
||||
for _, token := range "Press ESC / q to exit" {
|
||||
for _, token := range lines.statusText + " Press ESC / q to exit" {
|
||||
p.screen.SetContent(pos, height-1, token, nil, footerStyle)
|
||||
pos++
|
||||
}
|
||||
@ -168,6 +168,9 @@ func (p *_Pager) StartPaging(logger *log.Logger, screen tcell.Screen) {
|
||||
logger.Printf("Unhandled event type: %v", ev)
|
||||
}
|
||||
|
||||
// FIXME: If more events are ready, skip this redraw, that
|
||||
// should speed up mouse wheel scrolling
|
||||
|
||||
p._Redraw(logger)
|
||||
}
|
||||
}
|
||||
|
36
m/reader.go
36
m/reader.go
@ -2,9 +2,12 @@ package m
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
)
|
||||
|
||||
// Reader reads a file into an array of strings.
|
||||
@ -18,20 +21,24 @@ import (
|
||||
// FIXME: Make the reader read in the background, independently of what the pager is showing
|
||||
type Reader struct {
|
||||
lines []string
|
||||
name string
|
||||
name *string
|
||||
}
|
||||
|
||||
// Lines contains a number of lines from the reader, plus metadata
|
||||
type Lines struct {
|
||||
lines []string
|
||||
|
||||
// One-based number of the first of the lines
|
||||
// One-based line number of the first line returned
|
||||
firstLineOneBased int
|
||||
|
||||
// "monkey.txt: 1-23/45 51%"
|
||||
statusText string
|
||||
}
|
||||
|
||||
// NewReaderFromStream creates a new stream reader
|
||||
func NewReaderFromStream(reader io.Reader) (*Reader, error) {
|
||||
// FIXME: Close the stream when done reading it?
|
||||
// FIXME: If we have a filter process, wait for that after done reading the stream
|
||||
scanner := bufio.NewScanner(reader)
|
||||
var lines []string
|
||||
for scanner.Scan() {
|
||||
@ -84,10 +91,30 @@ func NewReaderFromFilename(filename string) (*Reader, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reader.name = filename
|
||||
reader.name = &filename
|
||||
return reader, err
|
||||
}
|
||||
|
||||
func (r *Reader) _CreateStatus(firstLineOneBased int, lastLineOneBased int) string {
|
||||
prefix := ""
|
||||
if r.name != nil {
|
||||
prefix = path.Base(*r.name) + ": "
|
||||
}
|
||||
|
||||
if len(r.lines) == 0 {
|
||||
return prefix + "<empty>"
|
||||
}
|
||||
|
||||
percent := int(math.Floor(100.0 * float64(lastLineOneBased) / float64(len(r.lines))))
|
||||
|
||||
return fmt.Sprintf("%s%d-%d/%d %d%%",
|
||||
prefix,
|
||||
firstLineOneBased,
|
||||
lastLineOneBased,
|
||||
len(r.lines),
|
||||
percent)
|
||||
}
|
||||
|
||||
// GetLines gets the indicated lines from the input
|
||||
func (r *Reader) GetLines(firstLineOneBased int, wantedLineCount int) *Lines {
|
||||
if firstLineOneBased < 1 {
|
||||
@ -100,6 +127,8 @@ func (r *Reader) GetLines(firstLineOneBased int, wantedLineCount int) *Lines {
|
||||
|
||||
// FIXME: What line number should we set here?
|
||||
firstLineOneBased: firstLineOneBased,
|
||||
|
||||
statusText: r._CreateStatus(0, 0),
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,5 +154,6 @@ func (r *Reader) GetLines(firstLineOneBased int, wantedLineCount int) *Lines {
|
||||
return &Lines{
|
||||
lines: r.lines[firstLineZeroBased : lastLineZeroBased+1],
|
||||
firstLineOneBased: firstLineOneBased,
|
||||
statusText: r._CreateStatus(firstLineOneBased, lastLineZeroBased+1),
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,14 @@ import (
|
||||
"math"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func _TestGetLines(t *testing.T, reader *Reader) {
|
||||
t.Logf("Testing file: %s...", reader.name)
|
||||
t.Logf("Testing file: %s...", *reader.name)
|
||||
|
||||
lines := reader.GetLines(1, 10)
|
||||
if len(lines.lines) > 10 {
|
||||
@ -99,3 +102,39 @@ func TestGetLines(t *testing.T) {
|
||||
_TestGetLines(t, reader)
|
||||
}
|
||||
}
|
||||
|
||||
func _GetReaderWithLineCount(totalLines int) *Reader {
|
||||
reader, err := NewReaderFromStream(strings.NewReader(strings.Repeat("x\n", totalLines)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return reader
|
||||
}
|
||||
|
||||
func _TestStatusText(t *testing.T, fromLine int, toLine int, totalLines int, expected string) {
|
||||
testMe := _GetReaderWithLineCount(totalLines)
|
||||
linesRequested := toLine - fromLine + 1
|
||||
statusText := testMe.GetLines(fromLine, linesRequested).statusText
|
||||
assert.Equal(t, statusText, expected)
|
||||
}
|
||||
|
||||
func TestStatusText(t *testing.T) {
|
||||
_TestStatusText(t, 1, 10, 20, "1-10/20 50%")
|
||||
_TestStatusText(t, 1, 5, 5, "1-5/5 100%")
|
||||
_TestStatusText(t, 998, 999, 1000, "998-999/1000 99%")
|
||||
|
||||
_TestStatusText(t, 0, 0, 0, "<empty>")
|
||||
_TestStatusText(t, 1, 1, 1, "1-1/1 100%")
|
||||
|
||||
// Test with filename
|
||||
testMe, err := NewReaderFromFilename("/dev/null")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
statusText := testMe.GetLines(0, 0).statusText
|
||||
assert.Equal(t, statusText, "null: <empty>")
|
||||
}
|
||||
|
||||
// FIXME: Add test for opening .gz files
|
||||
// FIXME: Add test for opening .xz files
|
||||
// FIXME: Add test for opening .bz2 files
|
||||
|
Loading…
Reference in New Issue
Block a user