A better way to print prettified json syntax error msg

This commit is contained in:
Anis ELLEUCH 2015-09-29 23:11:46 +01:00 committed by Harshavardhana
parent db293aedb7
commit b5ea05d839
14 changed files with 432 additions and 2 deletions

96
pkg/quick/errorutil.go Normal file
View File

@ -0,0 +1,96 @@
/*
* Quick - Quick key value store for config files and persistent state files
*
* Minio Client (C) 2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package quick
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"github.com/olekukonko/ts"
)
const errorFmt = "%5d: %s <-- "
// FormatJSONSyntaxError generates a pretty printed json syntax error since
// golang doesn't provide an easy way to report the location of the error
func FormatJSONSyntaxError(data io.Reader, sErr *json.SyntaxError) error {
if sErr == nil {
return nil
}
var readLine bytes.Buffer
bio := bufio.NewReader(data)
errLine := int64(1)
readBytes := int64(0)
// termWidth is set to a default one to use when we are
// not able to calculate terminal width via OS syscalls
termWidth := 25
// errorShift is the length of the minimum needed place for
// error msg accessoires, like <--, etc.. We calculate it
// dynamically to avoid an eventual bug after modifying errorFmt
errorShift := len(fmt.Sprintf(errorFmt, 1, ""))
if termSize, err := ts.GetSize(); err == nil {
termWidth = termSize.Col()
}
for {
b, err := bio.ReadByte()
if err != nil {
if err != io.EOF {
return err
}
break
}
readBytes++
if readBytes > sErr.Offset {
break
}
switch b {
case '\n':
readLine.Reset()
errLine++
case '\t':
readLine.WriteByte(' ')
case '\r':
break
default:
readLine.WriteByte(b)
}
}
lineLen := readLine.Len()
idx := lineLen - termWidth + errorShift
if idx < 0 || idx > lineLen-1 {
idx = 0
}
errorStr := fmt.Sprintf("JSON syntax error at line %d, col %d : %s.\n",
errLine, readLine.Len(), sErr)
errorStr += fmt.Sprintf(errorFmt, errLine, readLine.String()[idx:])
return errors.New(errorStr)
}

View File

@ -19,6 +19,7 @@
package quick
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
@ -144,7 +145,12 @@ func Load(filename string, data interface{}) (Config, *probe.Error) {
err = json.Unmarshal(fileData, &data)
if err != nil {
return nil, probe.NewError(err)
switch err := err.(type) {
case *json.SyntaxError:
return nil, probe.NewError(FormatJSONSyntaxError(bytes.NewReader(fileData), err))
default:
return nil, probe.NewError(err)
}
}
config, perr := New(data)
@ -182,7 +188,12 @@ func (d *config) Load(filename string) *probe.Error {
err = json.Unmarshal(fileData, d.data)
if err != nil {
return probe.NewError(err)
switch err := err.(type) {
case *json.SyntaxError:
return probe.NewError(FormatJSONSyntaxError(bytes.NewReader(fileData), err))
default:
return probe.NewError(err)
}
}
if err := CheckData(d.data); err != nil {

View File

@ -86,6 +86,13 @@
"revision": "ee386baecc113eef2b8945df429120a5aec319ef",
"revisionTime": "2015-08-19T11:23:55-07:00"
},
{
"canonical": "github.com/olekukonko/ts",
"comment": "",
"local": "vendor/github.com/olekukonko/ts",
"revision": "ecf753e7c962639ab5a1fb46f7da627d4c0a04b8",
"revisionTime": "2014-04-12T15:01:45-07:00"
},
{
"canonical": "github.com/rs/cors",
"comment": "",

19
vendor/github.com/olekukonko/ts/LICENCE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (C) 2014 by Oleku Konko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

28
vendor/github.com/olekukonko/ts/README.md generated vendored Normal file
View File

@ -0,0 +1,28 @@
ts (Terminal Size)
==
[![Build Status](https://travis-ci.org/olekukonko/ts.png?branch=master)](https://travis-ci.org/olekukonko/ts) [![Total views](https://sourcegraph.com/api/repos/github.com/olekukonko/ts/counters/views.png)](https://sourcegraph.com/github.com/olekukonko/ts)
Simple go Application to get Terminal Size. So Many Implementations do not support windows but `ts` has full windows support.
Run `go get github.com/olekukonko/ts` to download and install
#### Example
```go
package main
import (
"fmt"
"github.com/olekukonko/ts"
)
func main() {
size, _ := ts.GetSize()
fmt.Println(size.Col()) // Get Width
fmt.Println(size.Row()) // Get Height
fmt.Println(size.PosX()) // Get X position
fmt.Println(size.PosY()) // Get Y position
}
```
[See Documentation](http://godoc.org/github.com/olekukonko/ts)

36
vendor/github.com/olekukonko/ts/doc.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
/**
Simple go Application to get Terminal Size. So Many Implementations do not support windows but `ts` has full windows support.
Run `go get github.com/olekukonko/ts` to download and install
Installation
Minimum requirements are Go 1.1+ with fill Windows support
Example
package main
import (
"fmt"
"github.com/olekukonko/ts"
)
func main() {
size, _ := ts.GetSize()
fmt.Println(size.Col()) // Get Width
fmt.Println(size.Row()) // Get Height
fmt.Println(size.PosX()) // Get X position
fmt.Println(size.PosY()) // Get Y position
}
**/
package ts

36
vendor/github.com/olekukonko/ts/ts.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
// Return System Size
type Size struct {
row uint16
col uint16
posX uint16
posY uint16
}
// Get Terminal Width
func (w Size) Col() int {
return int(w.col)
}
// Get Terminal Height
func (w Size) Row() int {
return int(w.row)
}
// Get Position X
func (w Size) PosX() int {
return int(w.posX)
}
// Get Position Y
func (w Size) PosY() int {
return int(w.posY)
}

14
vendor/github.com/olekukonko/ts/ts_darwin.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// +build darwin
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
const (
TIOCGWINSZ = 0x40087468
)

13
vendor/github.com/olekukonko/ts/ts_linux.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
// +build linux
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
const (
TIOCGWINSZ = 0x5413
)

14
vendor/github.com/olekukonko/ts/ts_other.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// +build !windows,!darwin,!freebsd,!netbsd,!openbsd,!linux
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
const (
TIOCGWINSZ = 0
)

32
vendor/github.com/olekukonko/ts/ts_test.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
import (
"fmt"
"testing"
)
func ExampleGetSize() {
size, _ := GetSize()
fmt.Println(size.Col()) // Get Width
fmt.Println(size.Row()) // Get Height
fmt.Println(size.PosX()) // Get X position
fmt.Println(size.PosY()) // Get Y position
}
func TestSize(t *testing.T) {
size, err := GetSize()
if err != nil {
t.Fatal(err)
}
if size.Col() == 0 || size.Row() == 0 {
t.Fatalf("Screen Size Failed")
}
}

14
vendor/github.com/olekukonko/ts/ts_unix.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// +build freebsd netbsd openbsd
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
const (
TIOCGWINSZ = 0x40087468
)

64
vendor/github.com/olekukonko/ts/ts_windows.go generated vendored Normal file
View File

@ -0,0 +1,64 @@
// +build windows
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
import (
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
// Retrieves information about the specified console screen buffer.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
screenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
)
// Contains information about a console screen buffer.
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx
type CONSOLE_SCREEN_BUFFER_INFO struct {
DwSize COORD
DwCursorPosition COORD
WAttributes uint16
SrWindow SMALL_RECT
DwMaximumWindowSize COORD
}
// Defines the coordinates of a character cell in a console screen buffer.
// The origin of the coordinate system (0,0) is at the top, left cell of the buffer.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682119(v=vs.85).aspx
type COORD struct {
X, Y uint16
}
// Defines the coordinates of the upper left and lower right corners of a rectangle.
// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686311(v=vs.85).aspx
type SMALL_RECT struct {
Left, Top, Right, Bottom uint16
}
func GetSize() (ws Size, err error) {
var info CONSOLE_SCREEN_BUFFER_INFO
rc, _, err := screenBufferInfo.Call(
uintptr(syscall.Stdout),
uintptr(unsafe.Pointer(&info)))
if rc == 0 {
return ws, err
}
ws = Size{info.SrWindow.Bottom,
info.SrWindow.Right,
info.DwCursorPosition.X,
info.DwCursorPosition.Y}
return ws, nil
}

46
vendor/github.com/olekukonko/ts/ts_x.go generated vendored Normal file
View File

@ -0,0 +1,46 @@
// +build !windows
// Copyright 2014 Oleku Konko All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
// This module is a Terminal API for the Go Programming Language.
// The protocols were written in pure Go and works on windows and unix systems
package ts
import (
"syscall"
"unsafe"
)
// Get Windows Size
func GetSize() (ws Size, err error) {
_, _, ec := syscall.Syscall(syscall.SYS_IOCTL,
uintptr(syscall.Stdout),
uintptr(TIOCGWINSZ),
uintptr(unsafe.Pointer(&ws)))
err = getError(ec)
if TIOCGWINSZ == 0 && err != nil {
ws = Size{80, 25, 0, 0}
}
return ws, err
}
func getError(ec interface{}) (err error) {
switch v := ec.(type) {
case syscall.Errno: // Some implementation return syscall.Errno number
if v != 0 {
err = syscall.Errno(v)
}
case error: // Some implementation return error
err = ec.(error)
default:
err = nil
}
return
}