1
1
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:
Johan Walles 2021-04-20 08:46:49 +02:00
commit bc5e464147
8 changed files with 98 additions and 34 deletions

3
go.mod
View File

@ -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
View File

@ -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=

View File

@ -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

View File

@ -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)

View File

@ -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
View File

@ -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
View File

@ -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 ./...

View File

@ -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 {