mirror of
https://github.com/cheat/cheat.git
synced 2025-09-04 02:58:29 +02:00
Re-wrote from scratch in Golang
- Re-implemented the project in Golang, and deprecated Python entirely - Implemented several new, long-requested features - Refactored cheatsheets into a separate repository
This commit is contained in:
9
internal/cheatpath/cheatpath.go
Normal file
9
internal/cheatpath/cheatpath.go
Normal file
@ -0,0 +1,9 @@
|
||||
package cheatpath
|
||||
|
||||
// Cheatpath encapsulates cheatsheet path information
|
||||
type Cheatpath struct {
|
||||
Name string `yaml:name`
|
||||
Path string `yaml:path`
|
||||
ReadOnly bool `yaml:readonly`
|
||||
Tags []string `yaml:tags`
|
||||
}
|
19
internal/cheatpath/filter.go
Normal file
19
internal/cheatpath/filter.go
Normal file
@ -0,0 +1,19 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Filter filters all cheatpaths that are not named `name`
|
||||
func Filter(paths []Cheatpath, name string) ([]Cheatpath, error) {
|
||||
|
||||
// if a path of the given name exists, return it
|
||||
for _, path := range paths {
|
||||
if path.Name == name {
|
||||
return []Cheatpath{path}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, return an error
|
||||
return []Cheatpath{}, fmt.Errorf("cheatpath does not exist: %s", name)
|
||||
}
|
53
internal/cheatpath/filter_test.go
Normal file
53
internal/cheatpath/filter_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFilterSuccess asserts that the proper cheatpath is returned when the
|
||||
// requested cheatpath exists
|
||||
func TestFilterSuccess(t *testing.T) {
|
||||
|
||||
// init cheatpaths
|
||||
paths := []Cheatpath{
|
||||
Cheatpath{Name: "foo"},
|
||||
Cheatpath{Name: "bar"},
|
||||
Cheatpath{Name: "baz"},
|
||||
}
|
||||
|
||||
// filter the paths
|
||||
paths, err := Filter(paths, "bar")
|
||||
if err != nil {
|
||||
t.Errorf("failed to filter paths: %v", err)
|
||||
}
|
||||
|
||||
// assert that the expected path was returned
|
||||
if len(paths) != 1 {
|
||||
t.Errorf(
|
||||
"failed to return correct path count: want: 1, got: %d",
|
||||
len(paths),
|
||||
)
|
||||
}
|
||||
|
||||
if paths[0].Name != "bar" {
|
||||
t.Errorf("failed to return correct path: want: bar, got: %s", paths[0].Name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFilterFailure asserts that an error is returned when a non-existent
|
||||
// cheatpath is requested
|
||||
func TestFilterFailure(t *testing.T) {
|
||||
|
||||
// init cheatpaths
|
||||
paths := []Cheatpath{
|
||||
Cheatpath{Name: "foo"},
|
||||
Cheatpath{Name: "bar"},
|
||||
Cheatpath{Name: "baz"},
|
||||
}
|
||||
|
||||
// filter the paths
|
||||
paths, err := Filter(paths, "qux")
|
||||
if err == nil {
|
||||
t.Errorf("failed to return an error on non-existent cheatpath")
|
||||
}
|
||||
}
|
18
internal/cheatpath/validate.go
Normal file
18
internal/cheatpath/validate.go
Normal file
@ -0,0 +1,18 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Validate returns an error if the cheatpath is invalid
|
||||
func (c *Cheatpath) Validate() error {
|
||||
|
||||
if c.Name == "" {
|
||||
return fmt.Errorf("invalid cheatpath: name must be specified")
|
||||
}
|
||||
if c.Path == "" {
|
||||
return fmt.Errorf("invalid cheatpath: path must be specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
56
internal/cheatpath/validate_test.go
Normal file
56
internal/cheatpath/validate_test.go
Normal file
@ -0,0 +1,56 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestValidateValid asserts that valid cheatpaths validate successfully
|
||||
func TestValidateValid(t *testing.T) {
|
||||
|
||||
// initialize a valid cheatpath
|
||||
cheatpath := Cheatpath{
|
||||
Name: "foo",
|
||||
Path: "/foo",
|
||||
ReadOnly: false,
|
||||
Tags: []string{},
|
||||
}
|
||||
|
||||
// assert that no errors are returned
|
||||
if err := cheatpath.Validate(); err != nil {
|
||||
t.Errorf("failed to validate valid cheatpath: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateMissingName asserts that paths that are missing a name fail to
|
||||
// validate
|
||||
func TestValidateMissingName(t *testing.T) {
|
||||
|
||||
// initialize a valid cheatpath
|
||||
cheatpath := Cheatpath{
|
||||
Path: "/foo",
|
||||
ReadOnly: false,
|
||||
Tags: []string{},
|
||||
}
|
||||
|
||||
// assert that no errors are returned
|
||||
if err := cheatpath.Validate(); err == nil {
|
||||
t.Errorf("failed to invalidate cheatpath without name")
|
||||
}
|
||||
}
|
||||
|
||||
// TestValidateMissingPath asserts that paths that are missing a path fail to
|
||||
// validate
|
||||
func TestValidateMissingPath(t *testing.T) {
|
||||
|
||||
// initialize a valid cheatpath
|
||||
cheatpath := Cheatpath{
|
||||
Name: "foo",
|
||||
ReadOnly: false,
|
||||
Tags: []string{},
|
||||
}
|
||||
|
||||
// assert that no errors are returned
|
||||
if err := cheatpath.Validate(); err == nil {
|
||||
t.Errorf("failed to invalidate cheatpath without path")
|
||||
}
|
||||
}
|
24
internal/cheatpath/writeable.go
Normal file
24
internal/cheatpath/writeable.go
Normal file
@ -0,0 +1,24 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Writeable returns a writeable Cheatpath
|
||||
func Writeable(cheatpaths []Cheatpath) (Cheatpath, error) {
|
||||
|
||||
// iterate backwards over the cheatpaths
|
||||
// NB: we're going backwards because we assume that the most "local"
|
||||
// cheatpath will be specified last in the configs
|
||||
for i := len(cheatpaths) - 1; i >= 0; i-- {
|
||||
|
||||
// if the cheatpath is not read-only, it is writeable, and thus returned
|
||||
if cheatpaths[i].ReadOnly == false {
|
||||
return cheatpaths[i], nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// otherwise, return an error
|
||||
return Cheatpath{}, fmt.Errorf("no writeable cheatpaths found")
|
||||
}
|
50
internal/cheatpath/writeable_test.go
Normal file
50
internal/cheatpath/writeable_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package cheatpath
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestWriteableOK asserts that Writeable returns the appropriate cheatpath
|
||||
// when a writeable cheatpath exists
|
||||
func TestWriteableOK(t *testing.T) {
|
||||
|
||||
// initialize some cheatpaths
|
||||
cheatpaths := []Cheatpath{
|
||||
Cheatpath{Path: "/foo", ReadOnly: true},
|
||||
Cheatpath{Path: "/bar", ReadOnly: false},
|
||||
Cheatpath{Path: "/baz", ReadOnly: true},
|
||||
}
|
||||
|
||||
// get the writeable cheatpath
|
||||
got, err := Writeable(cheatpaths)
|
||||
|
||||
// assert that no errors were returned
|
||||
if err != nil {
|
||||
t.Errorf("failed to get cheatpath: %v", err)
|
||||
}
|
||||
|
||||
// assert that the path is correct
|
||||
if got.Path != "/bar" {
|
||||
t.Errorf("incorrect cheatpath returned: got: %s", got.Path)
|
||||
}
|
||||
}
|
||||
|
||||
// TestWriteableOK asserts that Writeable returns an error when no writeable
|
||||
// cheatpaths exist
|
||||
func TestWriteableNotOK(t *testing.T) {
|
||||
|
||||
// initialize some cheatpaths
|
||||
cheatpaths := []Cheatpath{
|
||||
Cheatpath{Path: "/foo", ReadOnly: true},
|
||||
Cheatpath{Path: "/bar", ReadOnly: true},
|
||||
Cheatpath{Path: "/baz", ReadOnly: true},
|
||||
}
|
||||
|
||||
// get the writeable cheatpath
|
||||
_, err := Writeable(cheatpaths)
|
||||
|
||||
// assert that no errors were returned
|
||||
if err == nil {
|
||||
t.Errorf("failed to return an error when no writeable paths found")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user