From b5ea05d83990836b902114ab43316c6bd728599f Mon Sep 17 00:00:00 2001 From: Anis ELLEUCH Date: Tue, 29 Sep 2015 23:11:46 +0100 Subject: [PATCH] A better way to print prettified json syntax error msg --- pkg/quick/errorutil.go | 96 +++++++++++++++++++ pkg/quick/quick.go | 15 ++- vendor.json | 7 ++ vendor/github.com/olekukonko/ts/LICENCE | 19 ++++ vendor/github.com/olekukonko/ts/README.md | 28 ++++++ vendor/github.com/olekukonko/ts/doc.go | 36 +++++++ vendor/github.com/olekukonko/ts/ts.go | 36 +++++++ vendor/github.com/olekukonko/ts/ts_darwin.go | 14 +++ vendor/github.com/olekukonko/ts/ts_linux.go | 13 +++ vendor/github.com/olekukonko/ts/ts_other.go | 14 +++ vendor/github.com/olekukonko/ts/ts_test.go | 32 +++++++ vendor/github.com/olekukonko/ts/ts_unix.go | 14 +++ vendor/github.com/olekukonko/ts/ts_windows.go | 64 +++++++++++++ vendor/github.com/olekukonko/ts/ts_x.go | 46 +++++++++ 14 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 pkg/quick/errorutil.go create mode 100644 vendor/github.com/olekukonko/ts/LICENCE create mode 100644 vendor/github.com/olekukonko/ts/README.md create mode 100644 vendor/github.com/olekukonko/ts/doc.go create mode 100644 vendor/github.com/olekukonko/ts/ts.go create mode 100644 vendor/github.com/olekukonko/ts/ts_darwin.go create mode 100644 vendor/github.com/olekukonko/ts/ts_linux.go create mode 100644 vendor/github.com/olekukonko/ts/ts_other.go create mode 100644 vendor/github.com/olekukonko/ts/ts_test.go create mode 100644 vendor/github.com/olekukonko/ts/ts_unix.go create mode 100644 vendor/github.com/olekukonko/ts/ts_windows.go create mode 100644 vendor/github.com/olekukonko/ts/ts_x.go diff --git a/pkg/quick/errorutil.go b/pkg/quick/errorutil.go new file mode 100644 index 000000000..b67582c40 --- /dev/null +++ b/pkg/quick/errorutil.go @@ -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) +} diff --git a/pkg/quick/quick.go b/pkg/quick/quick.go index c0b34193e..3aa6c6b24 100644 --- a/pkg/quick/quick.go +++ b/pkg/quick/quick.go @@ -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 { diff --git a/vendor.json b/vendor.json index 4cde87bc0..25da922ee 100755 --- a/vendor.json +++ b/vendor.json @@ -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": "", diff --git a/vendor/github.com/olekukonko/ts/LICENCE b/vendor/github.com/olekukonko/ts/LICENCE new file mode 100644 index 000000000..1fd848425 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/LICENCE @@ -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. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/ts/README.md b/vendor/github.com/olekukonko/ts/README.md new file mode 100644 index 000000000..4e1598b1c --- /dev/null +++ b/vendor/github.com/olekukonko/ts/README.md @@ -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) diff --git a/vendor/github.com/olekukonko/ts/doc.go b/vendor/github.com/olekukonko/ts/doc.go new file mode 100644 index 000000000..50c63cae0 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/doc.go @@ -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 diff --git a/vendor/github.com/olekukonko/ts/ts.go b/vendor/github.com/olekukonko/ts/ts.go new file mode 100644 index 000000000..35fdf7427 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts.go @@ -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) +} diff --git a/vendor/github.com/olekukonko/ts/ts_darwin.go b/vendor/github.com/olekukonko/ts/ts_darwin.go new file mode 100644 index 000000000..bdcf42b47 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_darwin.go @@ -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 +) diff --git a/vendor/github.com/olekukonko/ts/ts_linux.go b/vendor/github.com/olekukonko/ts/ts_linux.go new file mode 100644 index 000000000..ee2db6d47 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_linux.go @@ -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 +) diff --git a/vendor/github.com/olekukonko/ts/ts_other.go b/vendor/github.com/olekukonko/ts/ts_other.go new file mode 100644 index 000000000..bf8048192 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_other.go @@ -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 +) diff --git a/vendor/github.com/olekukonko/ts/ts_test.go b/vendor/github.com/olekukonko/ts/ts_test.go new file mode 100644 index 000000000..4998e7c01 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_test.go @@ -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") + } +} diff --git a/vendor/github.com/olekukonko/ts/ts_unix.go b/vendor/github.com/olekukonko/ts/ts_unix.go new file mode 100644 index 000000000..8728b614c --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_unix.go @@ -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 +) diff --git a/vendor/github.com/olekukonko/ts/ts_windows.go b/vendor/github.com/olekukonko/ts/ts_windows.go new file mode 100644 index 000000000..2f34d5699 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_windows.go @@ -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 +} diff --git a/vendor/github.com/olekukonko/ts/ts_x.go b/vendor/github.com/olekukonko/ts/ts_x.go new file mode 100644 index 000000000..1b260e381 --- /dev/null +++ b/vendor/github.com/olekukonko/ts/ts_x.go @@ -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 +}