mirror of
https://github.com/walles/moar.git
synced 2024-09-21 09:01:30 +03:00
Merge branch 'walles/errcheck'
This commit is contained in:
commit
bc5e464147
3
go.mod
3
go.mod
@ -1,11 +1,12 @@
|
||||
module github.com/walles/moar
|
||||
|
||||
go 1.16
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma v0.8.2
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/google/renameio v0.1.0 // indirect
|
||||
github.com/kisielk/errcheck v1.6.0 // indirect
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.3.0 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
|
7
go.sum
7
go.sum
@ -20,6 +20,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY=
|
||||
github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
@ -54,6 +56,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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=
|
||||
@ -62,12 +65,15 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
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=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
@ -98,6 +104,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -22,7 +22,11 @@ func TestTokenize(t *testing.T) {
|
||||
t.Errorf("Error opening file <%s>: %s", fileName, err.Error())
|
||||
continue
|
||||
}
|
||||
defer file.Close()
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
lineNumber := 0
|
||||
|
@ -190,8 +190,12 @@ func testManPageFormatting(t *testing.T, input string, expected twin.Cell) {
|
||||
|
||||
// Without these three lines the man page tests will fail if either of these
|
||||
// environment variables are set when the tests are run.
|
||||
os.Setenv("LESS_TERMCAP_md", "")
|
||||
os.Setenv("LESS_TERMCAP_us", "")
|
||||
if err := os.Setenv("LESS_TERMCAP_md", ""); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := os.Setenv("LESS_TERMCAP_us", ""); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
resetManPageFormatForTesting()
|
||||
|
||||
contents := startPaging(t, reader).GetRow(0)
|
||||
|
29
m/reader.go
29
m/reader.go
@ -64,15 +64,22 @@ func readStream(stream io.Reader, reader *Reader, fromFilter *exec.Cmd) {
|
||||
|
||||
// Give the filter a little time to go away
|
||||
timer := time.AfterFunc(2*time.Second, func() {
|
||||
fromFilter.Process.Kill()
|
||||
// FIXME: Regarding error handling, maybe we should log all errors
|
||||
// except for "process doesn't exist"? If the process is not there
|
||||
// it likely means the process finished up by itself without our
|
||||
// help.
|
||||
_ = fromFilter.Process.Kill()
|
||||
})
|
||||
|
||||
stderrText := ""
|
||||
if reader._stderr != nil {
|
||||
// Drain the reader's stderr into a string for possible inclusion in an error message
|
||||
buffer := new(bytes.Buffer)
|
||||
buffer.ReadFrom(reader._stderr)
|
||||
stderrText = strings.TrimSpace(buffer.String())
|
||||
// From: https://stackoverflow.com/a/9650373/473672
|
||||
if buffer, err := ioutil.ReadAll(reader._stderr); err == nil {
|
||||
stderrText = strings.TrimSpace(string(buffer))
|
||||
} else {
|
||||
log.Warn("Draining filter stderr failed: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := fromFilter.Wait()
|
||||
@ -263,18 +270,20 @@ func tryOpen(filename string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tryMe.Close()
|
||||
|
||||
// Try reading a byte
|
||||
buffer := make([]byte, 1)
|
||||
_, err = tryMe.Read(buffer)
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if err.Error() == "EOF" {
|
||||
if err != nil && err.Error() == "EOF" {
|
||||
// Empty file, this is fine
|
||||
return nil
|
||||
err = nil
|
||||
}
|
||||
|
||||
closeErr := tryMe.Close()
|
||||
if err == nil && closeErr != nil {
|
||||
// Everything worked up until Close(), report the Close() error
|
||||
return closeErr
|
||||
}
|
||||
|
||||
return err
|
||||
|
47
moar.go
47
moar.go
@ -23,11 +23,13 @@ func printUsage(output io.Writer) {
|
||||
// This controls where PrintDefaults() prints, see below
|
||||
flag.CommandLine.SetOutput(output)
|
||||
|
||||
fmt.Fprintln(output, "Usage:")
|
||||
fmt.Fprintln(output, " moar [options] <file>")
|
||||
fmt.Fprintln(output, " ... | moar")
|
||||
fmt.Fprintln(output, " moar < file")
|
||||
fmt.Fprintln(output)
|
||||
// FIXME: Log if any of these printouts fail?
|
||||
|
||||
_, _ = fmt.Fprintln(output, "Usage:")
|
||||
_, _ = fmt.Fprintln(output, " moar [options] <file>")
|
||||
_, _ = fmt.Fprintln(output, " ... | moar")
|
||||
_, _ = fmt.Fprintln(output, " moar < file")
|
||||
_, _ = fmt.Fprintln(output)
|
||||
|
||||
flag.PrintDefaults()
|
||||
|
||||
@ -39,11 +41,11 @@ func printUsage(output io.Writer) {
|
||||
}
|
||||
if pagerValue != moarPath {
|
||||
// We're not the default pager
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output, "To make Moar your default pager, put the following line in")
|
||||
fmt.Fprintln(output, "your .bashrc or .bash_profile and it will be default in all")
|
||||
fmt.Fprintln(output, "new terminal windows:")
|
||||
fmt.Fprintf(output, " export PAGER=%s\n", moarPath)
|
||||
_, _ = fmt.Fprintln(output)
|
||||
_, _ = fmt.Fprintln(output, "To make Moar your default pager, put the following line in")
|
||||
_, _ = fmt.Fprintln(output, "your .bashrc or .bash_profile and it will be default in all")
|
||||
_, _ = fmt.Fprintln(output, "new terminal windows:")
|
||||
_, _ = fmt.Fprintf(output, " export PAGER=%s\n", moarPath)
|
||||
}
|
||||
} else {
|
||||
log.Warn("Unable to find moar binary ", err)
|
||||
@ -109,7 +111,10 @@ func main() {
|
||||
stdinIsRedirected := !term.IsTerminal(int(os.Stdin.Fd()))
|
||||
stdoutIsRedirected := !term.IsTerminal(int(os.Stdout.Fd()))
|
||||
if stdinIsRedirected && stdoutIsRedirected {
|
||||
io.Copy(os.Stdout, os.Stdin)
|
||||
_, err := io.Copy(os.Stdout, os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to copy stdin to stdout: ", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@ -132,13 +137,27 @@ func main() {
|
||||
// Pump from file by given name onto stdout which is redirected
|
||||
input, err := os.Open(flag.Arg(0))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
||||
fmt.Fprintf(os.Stderr, "ERROR opening %s: %s\n", flag.Arg(0), err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer input.Close()
|
||||
defer func() {
|
||||
err := input.Close()
|
||||
if err != nil {
|
||||
log.Warn("Closing ", flag.Arg(0), " failed: ", err)
|
||||
|
||||
// NOTE: No os.Exit(1) here.
|
||||
//
|
||||
// Leaking this one file descriptior isn't serious enough to
|
||||
// warrant panicking or exiting with a non-zero code, so just
|
||||
// keep going.
|
||||
}
|
||||
}()
|
||||
|
||||
// Copy input file to redirected stdout
|
||||
io.Copy(os.Stdout, input)
|
||||
_, err = io.Copy(os.Stdout, input)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to copy ", flag.Arg(0), " to stdout: ", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
|
26
test.sh
26
test.sh
@ -5,6 +5,12 @@ set -e -o pipefail
|
||||
# Latest version: https://github.com/dominikh/go-tools/releases/latest
|
||||
STATICCHECK_VERSION=2020.2.3
|
||||
|
||||
# Latest version: https://github.com/kisielk/errcheck/releases/latest
|
||||
ERRCHECK_VERSION=v1.6.0
|
||||
|
||||
# Install our linters
|
||||
go get "honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION}" "github.com/kisielk/errcheck@${ERRCHECK_VERSION}"
|
||||
|
||||
# Test that we only pass tcell.Color constants to these methods, not numbers
|
||||
grep -En 'Foreground\([1-9]' ./*.go ./*/*.go && exit 1
|
||||
grep -En 'Background\([1-9]' ./*.go ./*/*.go && exit 1
|
||||
@ -13,6 +19,7 @@ grep -En 'Background\([1-9]' ./*.go ./*/*.go && exit 1
|
||||
./build.sh
|
||||
|
||||
# Linting
|
||||
echo "Checking code formatting..."
|
||||
MISFORMATTED="$(gofmt -l -s .)"
|
||||
if [ -n "$MISFORMATTED" ]; then
|
||||
echo >&2 "==="
|
||||
@ -23,28 +30,37 @@ if [ -n "$MISFORMATTED" ]; then
|
||||
fi
|
||||
|
||||
# "go vet" catches fmt-placeholders-vs-args problems (and others)
|
||||
echo "Running go vet..."
|
||||
if ! go vet . ./twin ./m ; then
|
||||
if [ -n "${CI}" ]; then
|
||||
echo >&2 "==="
|
||||
echo >&2 "=== Please run './test.sh' before pushing to see these issues locally rather than in CI"
|
||||
echo >&2 "=== Please run './test.sh' before pushing to see the above issues locally rather than in CI"
|
||||
echo >&2 "==="
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docs: https://staticcheck.io/docs/
|
||||
go get "honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION}"
|
||||
echo "Running staticcheck..."
|
||||
if ! "$(go env GOPATH)/bin/staticcheck" -f stylish . ./... ; then
|
||||
if [ -n "${CI}" ]; then
|
||||
echo >&2 "==="
|
||||
echo >&2 "=== Please run './test.sh' before pushing to see these issues locally rather than in CI"
|
||||
echo >&2 "=== Please run './test.sh' before pushing to see the above issues locally rather than in CI"
|
||||
echo >&2 "==="
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# FIXME: Add https://staticcheck.io/docs/
|
||||
# FIXME: Add https://github.com/kisielk/errcheck
|
||||
# Checks for unused error return values: https://github.com/kisielk/errcheck
|
||||
echo "Running errcheck to check for unused error return values..."
|
||||
if ! "$(go env GOPATH)/bin/errcheck" . ./... ; then
|
||||
if [ -n "${CI}" ]; then
|
||||
echo >&2 "==="
|
||||
echo >&2 "=== Please run './test.sh' before pushing to see the above issues locally rather than in CI"
|
||||
echo >&2 "==="
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Unit tests first
|
||||
go test -timeout 20s ./...
|
||||
|
@ -127,7 +127,11 @@ func (screen *UnixScreen) Close() {
|
||||
screen.hideCursor(false)
|
||||
screen.enableMouseTracking(false)
|
||||
screen.setAlternateScreenMode(false)
|
||||
screen.restoreTtyInTtyOut()
|
||||
|
||||
err := screen.restoreTtyInTtyOut()
|
||||
if err != nil {
|
||||
log.Warn("Problem restoring TTY state: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (screen *UnixScreen) Events() chan Event {
|
||||
|
Loading…
Reference in New Issue
Block a user