Skip to content

Commit

Permalink
Merge pull request #104 from essentialkaos/develop
Browse files Browse the repository at this point in the history
Version 7.3.0
  • Loading branch information
andyone authored Apr 1, 2017
2 parents 0a1fd51 + eb46c2f commit 4cf113d
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 43 deletions.
38 changes: 23 additions & 15 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## Changelog

### v7.3.0

* `[sortutil]` Added methods `NatualLess` and `StringsNatual` for natural ordering
* `[jsonutil]` Added optional argument to `EncodeToFile` method with file permissions (0644 by default)
* `[jsonutil]` Code refactoring
* `[jsonutil]` Improved tests
* `[jsonutil]` Added usage examples

### v7.2.0

* `[knf]` Return default value for the property even if config struct is nil
Expand Down Expand Up @@ -31,7 +39,7 @@
### v7.0.0

* `[usage]` Added interface for different ways to check application updates
* `[usage]` Added github update checker
* `[usage]` Added Github update checker
* `[usage]` Moved `CommandsColorTag`, `OptionsColorTag`, `Breadcrumbs` to `Info` struct (_incompatible changes_)
* `[fsutil]` Now `ListingFilter` must be passed as value instead of pointer (_incompatible changes_)
* `[fsutil]` Added support of filtering by size for `ListingFilter`
Expand Down Expand Up @@ -61,7 +69,7 @@

#### v6.0.0

* `[passwd]` Much secure hash generation (now with sha512, bcrypt and AES)
* `[passwd]` Much secure hash generation (now with sha512, bcrypt, and AES)
* `[system]` Improved changing process and arguments names
* `[system/process]` Fixed windows stubs

Expand Down Expand Up @@ -98,7 +106,7 @@

#### v5.4.0

* `[usage]` Changed color for arguments from dark grey to light grey
* `[usage]` Changed color for arguments from dark gray to light gray
* `[usage]` Added breadcrumbs output for commands and options
* `[fmtutil]` Fixed special symbols colorization in `ColorizePassword`

Expand Down Expand Up @@ -137,7 +145,7 @@
* `[crypto]` Package divided into multiple packages (`hash`, `passwd`, `uuid`)
* `[uuid]` Added UUID generation based on SHA-1 hash of namespace UUID and name (_version 5_)
* `[req]` Added different types support for `Query`
* `[knf]` Added `NotContains` validator which check if given config property contains any value from given slice
* `[knf]` Added `NotContains` validator which checks if given config property contains any value from given slice
* `[kv]` Using values instead pointers
* `[system]` Added custom duration support for `GetNetworkSpeed` and `GetIOUtil`
* `[version]` Improved version parsing
Expand All @@ -151,7 +159,7 @@

#### v3.5.1

* `[usage]` Using dark grey color for license and copyright
* `[usage]` Using dark gray color for license and copyright
* `[fmtutil]` Added global variable `SeparatorColorTag` for separator color customization
* `[fmtutil]` Added global variable `SeparatorTitleColorTag` for separator title color customization

Expand All @@ -160,7 +168,7 @@
* `[terminal]` Using forked [go.linenoise](https://github.com/essentialkaos/go-linenoise) package instead original
* `[terminal]` Added hints support from new version of `go.linenoise`
* `[fmtc]` Light colors tag (`-`) support
* `[usage]` Using dark grey color for option values and example description
* `[usage]` Using dark gray color for option values and example description
* `[tmp]` Added `DefaultDirPerms` and `DefaultFilePerms` global variables for permissions customization
* `[tmp]` Improved error handling

Expand Down Expand Up @@ -201,8 +209,8 @@

#### v3.2.0

* `[strutil]` Added method `Len` which return number of symbols in string
* `[strutil]` UTF-8 support for `Substr`, `Tail`, `Head` and `Elipsis` methods
* `[strutil]` Added method `Len` which returns number of symbols in string
* `[strutil]` UTF-8 support for `Substr`, `Tail`, `Head` and `Ellipsis` methods
* `[strutil]` Added some benchmarks to tests
* `[fsutil]` Fixed `GetPerm` stub for Windows
* `[fsutil]` Fixed package description
Expand Down Expand Up @@ -256,7 +264,7 @@

#### v2.0.2

* `[pid]` Added method `IsWorks` which return true if process with pid from pidfile is active
* `[pid]` Added method `IsWorks` which return true if process with PID from PID file is active
* `[pid]` Increased code coverage

#### v2.0.1
Expand All @@ -271,7 +279,7 @@
* `[terminal]` Improved reading y/n answers (_incompatible changes_)
* `[strutil]` Added method `Fields` for "smart" string splitting
* `[system]` Methods `GetUsername` and `GetGroupname` deprecated
* `[system]` Added method `GroupList` for user struct which return slice with user groups names
* `[system]` Added method `GroupList` for user struct which returns slice with user groups names
* `[jsonutil]` Code refactoring
* `[usage]` Code refactoring

Expand Down Expand Up @@ -310,7 +318,7 @@

#### v1.7.6

* `[env]` Added methods for getting env vars as string, int and float
* `[env]` Added methods for getting env vars as string, int, and float

#### v1.7.5

Expand Down Expand Up @@ -366,7 +374,7 @@

#### v1.5.1

* `[knf]` Fixed bug in HasProp method which return true for unset properties
* `[knf]` Fixed bug in HasProp method which returns true for unset properties

#### v1.5.0

Expand All @@ -375,7 +383,7 @@

#### v1.4.5

* `[pid]` Fixed bug with pid file creation
* `[pid]` Fixed bug with PID file creation
* `[pid]` Increased coverage

#### v1.4.4
Expand Down Expand Up @@ -444,9 +452,9 @@

#### v1.1.1

* `[system]` Added json tags for User, Group and SessionInfo structs
* `[system]` Added JSON tags for User, Group and SessionInfo structs
* `[usage]` Info now can use os.Args`[0]` for info rendering
* `[version]` Added package for working with version in simver notation
* `[version]` Added package for working with version in semver notation

#### v1.1

Expand Down
4 changes: 2 additions & 2 deletions fmtc/fmtc.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var codes = map[rune]int{
'b': 34, // Blue
'm': 35, // Magenta
'c': 36, // Cyan
's': 37, // Grey (Smokey)
's': 37, // Gray (Smokey)
'w': 97, // White

// Background
Expand All @@ -61,7 +61,7 @@ var codes = map[rune]int{
'B': 44, // Blue
'M': 45, // Magenta
'C': 46, // Cyan
'S': 47, // Grey (Smokey)
'S': 47, // Gray (Smokey)
'W': 107, // White
}

Expand Down
37 changes: 37 additions & 0 deletions jsonutil/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package jsonutil

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2009-2017 ESSENTIAL KAOS //
// Essential Kaos Open Source License <https://essentialkaos.com/ekol> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import (
"fmt"
)

// ////////////////////////////////////////////////////////////////////////////////// //

func ExampleEncodeToFile() {
var data = make(map[string]int)

data["john"] = 100
data["bob"] = 300

err := EncodeToFile("/path/to/file.json", data, 0600)

if err != nil {
fmt.Printf("Error: %v\n", err)
}
}

func ExampleDecodeFile() {
var data = make(map[string]int)

err := DecodeFile("/path/to/file.json", data)

if err != nil {
fmt.Printf("Error: %v\n", err)
}
}
34 changes: 14 additions & 20 deletions jsonutil/jsonutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,34 @@ import (

// ////////////////////////////////////////////////////////////////////////////////// //

// DecodeFile reads and decode json file
func DecodeFile(file string, v interface{}) error {
data, err := ioutil.ReadFile(file)

if err != nil {
return err
}

return json.Unmarshal(data, v)
}

// EncodeToFile encode data to json and save to file
func EncodeToFile(file string, v interface{}) error {
fd, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0644)
func EncodeToFile(file string, v interface{}, perms ...os.FileMode) error {
jsonData, err := json.MarshalIndent(v, "", " ")

if err != nil {
return err
}

defer fd.Close()
if jsonData[len(jsonData)-1] != '\n' {
jsonData = append(jsonData, byte('\n'))
}

jsonData, err := json.MarshalIndent(v, "", " ")
var perm os.FileMode = 0644

if err != nil {
return err
if len(perms) > 0 {
perm = perms[0]
}

jsonData = append(jsonData, byte('\n'))
return ioutil.WriteFile(file, jsonData, perm)
}

_, err = fd.Write(jsonData)
// DecodeFile reads and decode json file
func DecodeFile(file string, v interface{}) error {
data, err := ioutil.ReadFile(file)

if err != nil {
return err
}

return nil
return json.Unmarshal(data, v)
}
16 changes: 10 additions & 6 deletions jsonutil/jsonutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ package jsonutil

import (
"io/ioutil"
"os"
"testing"

. "pkg.re/check.v1"

"pkg.re/essentialkaos/ek.v7/hash"
"pkg.re/essentialkaos/ek.v7/fsutil"
)

// ////////////////////////////////////////////////////////////////////////////////// //
Expand Down Expand Up @@ -57,8 +58,6 @@ func (s *JSONSuite) TestDecoding(c *C) {
err := ioutil.WriteFile(jsonFile, []byte(_JSON_DATA), 0644)

c.Assert(err, IsNil)
c.Assert(hash.FileHash(jsonFile), Equals,
"b88184cc9c6c517e572a21acae7118d58c485b051c33f3f13d057b43461c4eec")

testStruct := &TestStruct{}

Expand All @@ -83,11 +82,16 @@ func (s *JSONSuite) TestEncoding(c *C) {
Boolean: true,
}

err := EncodeToFile(jsonFile, testStruct)
err := EncodeToFile(jsonFile, testStruct, 0640)

c.Assert(err, IsNil)
c.Assert(hash.FileHash(jsonFile), Equals,
"b88184cc9c6c517e572a21acae7118d58c485b051c33f3f13d057b43461c4eec")
c.Assert(fsutil.GetPerm(jsonFile), Equals, os.FileMode(0640))

data, err := ioutil.ReadFile(jsonFile)

c.Assert(err, IsNil)
c.Assert(string(data), Equals, _JSON_DATA)
c.Assert(string(data), Equals, _JSON_DATA)

err = EncodeToFile("/test.json", testStruct)

Expand Down
95 changes: 95 additions & 0 deletions sortutil/natural.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package sortutil

// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2009-2017 ESSENTIAL KAOS //
// Essential Kaos Open Source License <https://essentialkaos.com/ekol> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //

import "sort"

// ////////////////////////////////////////////////////////////////////////////////// //

type naturalSlice []string

func (s naturalSlice) Len() int { return len(s) }
func (s naturalSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s naturalSlice) Less(i, j int) bool { return NaturalLess(s[i], s[j]) }

// ////////////////////////////////////////////////////////////////////////////////// //

// StringsNatural sorts a slice of strings in natural order
// Limitation: only ASCII digits (0-9) are considered.
func StringsNatural(a []string) {
sort.Sort(naturalSlice(a))
}

// NaturalLess compares two strings using natural ordering. This means that e.g.
// "abc2" < "abc12"
// This code based on sortorder package created by @fvbommel
func NaturalLess(s1, s2 string) bool {
i1, i2 := 0, 0
l1, l2 := len(s1), len(s2)

for i1 < l1 && i2 < l2 {
c1, c2 := s1[i1], s2[i2]
d1, d2 := isDigit(c1), isDigit(c2)

if d1 != d2 {
return d1
} else if !d1 {
if c1 != c2 {
return c1 < c2
}

i1++
i2++

continue
}

for i1 < l1 && s1[i1] == '0' {
i1++
}

for i2 < l2 && s2[i2] == '0' {
i2++
}

n1, n2 := i1, i2

for i1 < l1 && isDigit(s1[i1]) {
i1++
}

for i2 < l2 && isDigit(s2[i2]) {
i2++
}

ln1, ln2 := i1-n1, i2-n2

if ln1 != ln2 {
return ln1 < ln2
}

nl1, nl2 := s1[n1:i1], s2[n2:i2]

if nl1 != nl2 {
return nl1 < nl2
}
}

return l1 < l2
}

// ////////////////////////////////////////////////////////////////////////////////// //

func isDigit(b byte) bool {
switch b {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return true
default:
return false
}
}
Loading

0 comments on commit 4cf113d

Please sign in to comment.