mirror of
https://github.com/cheat/cheat.git
synced 2025-09-01 17:48:30 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
219db679e1 | |||
53177cb09d | |||
ef7a41f9a9 | |||
008316d030 | |||
a59c019642 | |||
57225442be | |||
2c7ce48859 | |||
a3fe4f40bb | |||
506fb8be15 | |||
408e944eea | |||
8a313b92ca | |||
6912771c39 | |||
d4c6200702 | |||
9251849d23 | |||
313b5ebd27 | |||
ca91b25b02 | |||
bbf6af50b1 | |||
9f05442bce | |||
3fc4c2f89e | |||
9e88ff2642 |
@ -3,6 +3,10 @@ language: go
|
|||||||
go:
|
go:
|
||||||
- 1.13.x
|
- 1.13.x
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- GO111MODULE=on
|
- GO111MODULE=on
|
||||||
|
|
||||||
|
23
Makefile
23
Makefile
@ -21,6 +21,7 @@ ZIP := zip -m
|
|||||||
# build flags
|
# build flags
|
||||||
BUILD_FLAGS := -ldflags="-s -w" -mod vendor -trimpath
|
BUILD_FLAGS := -ldflags="-s -w" -mod vendor -trimpath
|
||||||
GOBIN :=
|
GOBIN :=
|
||||||
|
TMPDIR := /tmp
|
||||||
|
|
||||||
# release binaries
|
# release binaries
|
||||||
releases := \
|
releases := \
|
||||||
@ -33,7 +34,7 @@ releases := \
|
|||||||
|
|
||||||
## build: builds an executable for your architecture
|
## build: builds an executable for your architecture
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(dist_dir)
|
build: $(dist_dir) clean generate
|
||||||
$(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir)
|
$(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir)
|
||||||
|
|
||||||
## build-release: builds release executables
|
## build-release: builds release executables
|
||||||
@ -47,27 +48,27 @@ ci: | setup prepare build
|
|||||||
# cheat-darwin-amd64
|
# cheat-darwin-amd64
|
||||||
$(dist_dir)/cheat-darwin-amd64: prepare
|
$(dist_dir)/cheat-darwin-amd64: prepare
|
||||||
GOARCH=amd64 GOOS=darwin \
|
GOARCH=amd64 GOOS=darwin \
|
||||||
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
# cheat-linux-amd64
|
# cheat-linux-amd64
|
||||||
$(dist_dir)/cheat-linux-amd64: prepare
|
$(dist_dir)/cheat-linux-amd64: prepare
|
||||||
GOARCH=amd64 GOOS=linux \
|
GOARCH=amd64 GOOS=linux \
|
||||||
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
# cheat-linux-arm5
|
# cheat-linux-arm5
|
||||||
$(dist_dir)/cheat-linux-arm5: prepare
|
$(dist_dir)/cheat-linux-arm5: prepare
|
||||||
GOARCH=arm GOOS=linux GOARM=5 \
|
GOARCH=arm GOOS=linux GOARM=5 \
|
||||||
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
# cheat-linux-arm6
|
# cheat-linux-arm6
|
||||||
$(dist_dir)/cheat-linux-arm6: prepare
|
$(dist_dir)/cheat-linux-arm6: prepare
|
||||||
GOARCH=arm GOOS=linux GOARM=6 \
|
GOARCH=arm GOOS=linux GOARM=6 \
|
||||||
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
# cheat-linux-arm7
|
# cheat-linux-arm7
|
||||||
$(dist_dir)/cheat-linux-arm7: prepare
|
$(dist_dir)/cheat-linux-arm7: prepare
|
||||||
GOARCH=arm GOOS=linux GOARM=7 \
|
GOARCH=arm GOOS=linux GOARM=7 \
|
||||||
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
# cheat-windows-amd64
|
# cheat-windows-amd64
|
||||||
$(dist_dir)/cheat-windows-amd64.exe: prepare
|
$(dist_dir)/cheat-windows-amd64.exe: prepare
|
||||||
@ -95,7 +96,7 @@ clean: $(dist_dir)
|
|||||||
## distclean: removes the tags file
|
## distclean: removes the tags file
|
||||||
.PHONY: distclean
|
.PHONY: distclean
|
||||||
distclean:
|
distclean:
|
||||||
$(RM) tags
|
$(RM) -f tags
|
||||||
|
|
||||||
## setup: installs revive (linter) and scc (sloc tool)
|
## setup: installs revive (linter) and scc (sloc tool)
|
||||||
.PHONY: setup
|
.PHONY: setup
|
||||||
@ -110,7 +111,7 @@ sloc:
|
|||||||
## tags: builds a tags file
|
## tags: builds a tags file
|
||||||
.PHONY: tags
|
.PHONY: tags
|
||||||
tags:
|
tags:
|
||||||
$(CTAGS) -R . --exclude=vendor
|
$(CTAGS) -R --exclude=vendor --languages=go
|
||||||
|
|
||||||
## vendor: downloads, tidies, and verifies dependencies
|
## vendor: downloads, tidies, and verifies dependencies
|
||||||
.PHONY: vendor
|
.PHONY: vendor
|
||||||
@ -137,6 +138,12 @@ vet:
|
|||||||
test:
|
test:
|
||||||
$(GO) test ./...
|
$(GO) test ./...
|
||||||
|
|
||||||
|
## coverage: generates a test coverage report
|
||||||
|
.PHONY: coverage
|
||||||
|
coverage:
|
||||||
|
$(GO) test ./... -coverprofile=$(TMPDIR)/cheat-coverage.out && \
|
||||||
|
$(GO) tool cover -html=$(TMPDIR)/cheat-coverage.out
|
||||||
|
|
||||||
## check: formats, lints, vets, vendors, and run unit-tests
|
## check: formats, lints, vets, vendors, and run unit-tests
|
||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: | vendor fmt lint vet test
|
check: | vendor fmt lint vet test
|
||||||
|
12
README.md
12
README.md
@ -193,9 +193,17 @@ cheat -p personal -t networking --regex -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
|||||||
|
|
||||||
Advanced Usage
|
Advanced Usage
|
||||||
--------------
|
--------------
|
||||||
`cheat` may be integrated with [fzf][]. See [fzf.bash][bash] for instructions.
|
Shell autocompletion is currently available for the `bash` and `fish` shells.
|
||||||
(Support for other shells will be added in future releases.)
|
Copy the relevant [completion script][completion-scripts] into the appropriate
|
||||||
|
directory on your filesystem to enable autocompletion. (This directory will
|
||||||
|
vary depending on operating system and shell specifics.)
|
||||||
|
|
||||||
|
Additionally, `cheat` supports enhanced autocompletion via integration with
|
||||||
|
[fzf][]. (This feature is currently available on bash only.) To enable `fzf`
|
||||||
|
integration:
|
||||||
|
|
||||||
|
1. Ensure that `fzf` is available on your `$PATH`
|
||||||
|
2. Set an envvar: `export CHEAT_USE_FZF=true`
|
||||||
|
|
||||||
[Releases]: https://github.com/cheat/cheat/releases
|
[Releases]: https://github.com/cheat/cheat/releases
|
||||||
[bash]: https://github.com/cheat/cheat/blob/master/scripts/fzf.bash
|
[bash]: https://github.com/cheat/cheat/blob/master/scripts/fzf.bash
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# TODO: this script has been made obsolete by the Makefile, yet downstream
|
|
||||||
# package managers plausibly rely on it for compiling locally. Remove this file
|
|
||||||
# after downstream maintainers have had time to modify their packages to simply
|
|
||||||
# invoke `make` in the project root.
|
|
||||||
|
|
||||||
# locate the cheat project root
|
|
||||||
BINDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
APPDIR=$(readlink -f "$BINDIR/..")
|
|
||||||
|
|
||||||
# compile the executable
|
|
||||||
cd $APPDIR
|
|
||||||
|
|
||||||
make
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docopt/docopt-go"
|
"github.com/docopt/docopt-go"
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "3.3.2"
|
const version = "3.5.0"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
@ -31,13 +32,42 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the config file
|
// read the envvars into a map of strings
|
||||||
confpath, err := config.Path(runtime.GOOS)
|
envvars := map[string]string{}
|
||||||
|
for _, e := range os.Environ() {
|
||||||
|
pair := strings.SplitN(e, "=", 2)
|
||||||
|
envvars[pair[0]] = pair[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the os-specifc paths at which the config file may be located
|
||||||
|
confpaths, err := config.Paths(runtime.GOOS, envvars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "could not locate config file")
|
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search for the config file in the above paths
|
||||||
|
confpath, err := config.Path(confpaths)
|
||||||
|
if err != nil {
|
||||||
|
|
||||||
|
// the config file does not exist, so we'll try to create one
|
||||||
|
if err = config.Init(confpaths[0], configs()); err != nil {
|
||||||
|
fmt.Fprintf(
|
||||||
|
os.Stderr,
|
||||||
|
"failed to create config file: %s: %v\n",
|
||||||
|
confpaths[0],
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
confpath = confpaths[0]
|
||||||
|
|
||||||
|
fmt.Printf("Created config file: %s\n", confpath)
|
||||||
|
fmt.Println("Please edit this file now to configure cheat.")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
// initialize the configs
|
// initialize the configs
|
||||||
conf, err := config.New(opts, confpath, true)
|
conf, err := config.New(opts, confpath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -43,22 +43,23 @@ cheatpaths:
|
|||||||
#
|
#
|
||||||
# Note that the paths and tags listed below are just examples. You may freely
|
# Note that the paths and tags listed below are just examples. You may freely
|
||||||
# change them to suit your needs.
|
# change them to suit your needs.
|
||||||
|
#
|
||||||
|
# TODO: regarding community cheatsheets: these must be installed separately.
|
||||||
|
# You may download them here:
|
||||||
|
#
|
||||||
|
# https://github.com/cheat/cheatsheets
|
||||||
|
#
|
||||||
|
# Once downloaded, ensure that 'path' below points to the location at which
|
||||||
|
# you downloaded the community cheatsheets.
|
||||||
- name: community
|
- name: community
|
||||||
path: ~/.dotfiles/cheat/community
|
path: ~/cheat/cheatsheets/community
|
||||||
tags: [ community ]
|
tags: [ community ]
|
||||||
readonly: true
|
readonly: true
|
||||||
|
|
||||||
# Maybe your company or department maintains a repository of cheatsheets as
|
|
||||||
# well. It's probably sensible to list those second.
|
|
||||||
- name: work
|
|
||||||
path: ~/.dotfiles/cheat/work
|
|
||||||
tags: [ work ]
|
|
||||||
readonly: false
|
|
||||||
|
|
||||||
# If you have personalized cheatsheets, list them last. They will take
|
# If you have personalized cheatsheets, list them last. They will take
|
||||||
# precedence over the more global cheatsheets.
|
# precedence over the more global cheatsheets.
|
||||||
- name: personal
|
- name: personal
|
||||||
path: ~/.dotfiles/cheat/personal
|
path: ~/cheat/cheatsheets/personal
|
||||||
tags: [ personal ]
|
tags: [ personal ]
|
||||||
readonly: false
|
readonly: false
|
||||||
|
|
||||||
|
@ -34,22 +34,23 @@ cheatpaths:
|
|||||||
#
|
#
|
||||||
# Note that the paths and tags listed below are just examples. You may freely
|
# Note that the paths and tags listed below are just examples. You may freely
|
||||||
# change them to suit your needs.
|
# change them to suit your needs.
|
||||||
|
#
|
||||||
|
# TODO: regarding community cheatsheets: these must be installed separately.
|
||||||
|
# You may download them here:
|
||||||
|
#
|
||||||
|
# https://github.com/cheat/cheatsheets
|
||||||
|
#
|
||||||
|
# Once downloaded, ensure that 'path' below points to the location at which
|
||||||
|
# you downloaded the community cheatsheets.
|
||||||
- name: community
|
- name: community
|
||||||
path: ~/.dotfiles/cheat/community
|
path: ~/cheat/cheatsheets/community
|
||||||
tags: [ community ]
|
tags: [ community ]
|
||||||
readonly: true
|
readonly: true
|
||||||
|
|
||||||
# Maybe your company or department maintains a repository of cheatsheets as
|
|
||||||
# well. It's probably sensible to list those second.
|
|
||||||
- name: work
|
|
||||||
path: ~/.dotfiles/cheat/work
|
|
||||||
tags: [ work ]
|
|
||||||
readonly: false
|
|
||||||
|
|
||||||
# If you have personalized cheatsheets, list them last. They will take
|
# If you have personalized cheatsheets, list them last. They will take
|
||||||
# precedence over the more global cheatsheets.
|
# precedence over the more global cheatsheets.
|
||||||
- name: personal
|
- name: personal
|
||||||
path: ~/.dotfiles/cheat/personal
|
path: ~/cheat/cheatsheets/personal
|
||||||
tags: [ personal ]
|
tags: [ personal ]
|
||||||
readonly: false
|
readonly: false
|
||||||
|
|
||||||
|
@ -75,14 +75,16 @@ func New(opts map[string]interface{}, confPath string, resolve bool) (Config, er
|
|||||||
// `resolve` is a switch that allows us to turn off symlink resolution when
|
// `resolve` is a switch that allows us to turn off symlink resolution when
|
||||||
// running the config tests.
|
// running the config tests.
|
||||||
if resolve {
|
if resolve {
|
||||||
expanded, err = filepath.EvalSymlinks(expanded)
|
evaled, err := filepath.EvalSymlinks(expanded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Config{}, fmt.Errorf(
|
return Config{}, fmt.Errorf(
|
||||||
"failed to resolve symlink: %s, %v",
|
"failed to resolve symlink: %s: %v",
|
||||||
expanded,
|
expanded,
|
||||||
err,
|
err,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expanded = evaled
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.Cheatpaths[i].Path = expanded
|
conf.Cheatpaths[i].Path = expanded
|
||||||
|
24
internal/config/init.go
Normal file
24
internal/config/init.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init initializes a config file
|
||||||
|
func Init(confpath string, configs string) error {
|
||||||
|
|
||||||
|
// assert that the config directory exists
|
||||||
|
if err := os.MkdirAll(filepath.Dir(confpath), 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the config file
|
||||||
|
if err := ioutil.WriteFile(confpath, []byte(configs), 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -3,43 +3,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Path returns the config file path
|
// Path returns the config file path
|
||||||
func Path(sys string) (string, error) {
|
func Path(paths []string) (string, error) {
|
||||||
|
|
||||||
var paths []string
|
|
||||||
|
|
||||||
// if CHEAT_CONFIG_PATH is set, return it
|
|
||||||
if os.Getenv("CHEAT_CONFIG_PATH") != "" {
|
|
||||||
|
|
||||||
// expand ~
|
|
||||||
expanded, err := homedir.Expand(os.Getenv("CHEAT_CONFIG_PATH"))
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to expand ~: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return expanded, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch sys {
|
|
||||||
case "darwin", "linux", "freebsd":
|
|
||||||
paths = []string{
|
|
||||||
path.Join(os.Getenv("XDG_CONFIG_HOME"), "/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".config/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".cheat/conf.yml"),
|
|
||||||
}
|
|
||||||
case "windows":
|
|
||||||
paths = []string{
|
|
||||||
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("APPDATA")),
|
|
||||||
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("PROGRAMDATA")),
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("unsupported os: %s", sys)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the config file exists on any paths
|
// check if the config file exists on any paths
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
|
50
internal/config/paths.go
Normal file
50
internal/config/paths.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Paths returns config file paths that are appropriate for the operating
|
||||||
|
// system
|
||||||
|
func Paths(sys string, envvars map[string]string) ([]string, error) {
|
||||||
|
|
||||||
|
// if `CHEAT_CONFIG_PATH` is set, expand ~ and return it
|
||||||
|
if confpath, ok := envvars["CHEAT_CONFIG_PATH"]; ok {
|
||||||
|
|
||||||
|
// expand ~
|
||||||
|
expanded, err := homedir.Expand(confpath)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, fmt.Errorf("failed to expand ~: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{expanded}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch sys {
|
||||||
|
case "darwin", "linux", "freebsd":
|
||||||
|
paths := []string{}
|
||||||
|
|
||||||
|
// don't include the `XDG_CONFIG_HOME` path if that envvar is not set
|
||||||
|
if xdgpath, ok := envvars["XDG_CONFIG_HOME"]; ok {
|
||||||
|
paths = append(paths, path.Join(xdgpath, "/cheat/conf.yml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// `HOME` will always be set on a POSIX-compliant system, though
|
||||||
|
paths = append(paths, []string{
|
||||||
|
path.Join(envvars["HOME"], ".config/cheat/conf.yml"),
|
||||||
|
path.Join(envvars["HOME"], ".cheat/conf.yml"),
|
||||||
|
}...)
|
||||||
|
|
||||||
|
return paths, nil
|
||||||
|
case "windows":
|
||||||
|
return []string{
|
||||||
|
path.Join(envvars["APPDATA"], "/cheat/conf.yml"),
|
||||||
|
path.Join(envvars["PROGRAMDATA"], "/cheat/conf.yml"),
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return []string{}, fmt.Errorf("unsupported os: %s", sys)
|
||||||
|
}
|
||||||
|
}
|
165
internal/config/paths_test.go
Normal file
165
internal/config/paths_test.go
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestValidatePathsNix asserts that the proper config paths are returned on
|
||||||
|
// *nix platforms
|
||||||
|
func TestValidatePathsNix(t *testing.T) {
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"HOME": "/home/foo",
|
||||||
|
"XDG_CONFIG_HOME": "/home/bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the platforms to test
|
||||||
|
oses := []string{
|
||||||
|
"darwin",
|
||||||
|
"freebsd",
|
||||||
|
"linux",
|
||||||
|
}
|
||||||
|
|
||||||
|
// test each *nix os
|
||||||
|
for _, os := range oses {
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths(os, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/bar/cheat/conf.yml",
|
||||||
|
"/home/foo/.config/cheat/conf.yml",
|
||||||
|
"/home/foo/.cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsNixNoXDG asserts that the proper config paths are returned
|
||||||
|
// on *nix platforms when `XDG_CONFIG_HOME is not set
|
||||||
|
func TestValidatePathsNixNoXDG(t *testing.T) {
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"HOME": "/home/foo",
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the platforms to test
|
||||||
|
oses := []string{
|
||||||
|
"darwin",
|
||||||
|
"freebsd",
|
||||||
|
"linux",
|
||||||
|
}
|
||||||
|
|
||||||
|
// test each *nix os
|
||||||
|
for _, os := range oses {
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths(os, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/foo/.config/cheat/conf.yml",
|
||||||
|
"/home/foo/.cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsWindows asserts that the proper config paths are returned
|
||||||
|
// on Windows platforms
|
||||||
|
func TestValidatePathsWindows(t *testing.T) {
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"APPDATA": "/apps",
|
||||||
|
"PROGRAMDATA": "/programs",
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths("windows", envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/apps/cheat/conf.yml",
|
||||||
|
"/programs/cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsUnsupported asserts that an error is returned on
|
||||||
|
// unsupported platforms
|
||||||
|
func TestValidatePathsUnsupported(t *testing.T) {
|
||||||
|
_, err := Paths("unsupported", map[string]string{})
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("failed to return error on unsupported platform")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsCheatConfigPath asserts that the proper config path is
|
||||||
|
// returned when `CHEAT_CONFIG_PATH` is explicitly specified.
|
||||||
|
func TestValidatePathsCheatConfigPath(t *testing.T) {
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"HOME": "/home/foo",
|
||||||
|
"XDG_CONFIG_HOME": "/home/bar",
|
||||||
|
"CHEAT_CONFIG_PATH": "/home/baz/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths("linux", envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/baz/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
function _cheat_autocomplete {
|
|
||||||
sheets=$(cheat -l | sed -n '2,$p'|cut -d' ' -f1)
|
|
||||||
COMPREPLY=()
|
|
||||||
if [ $COMP_CWORD = 1 ]; then
|
|
||||||
COMPREPLY=(`compgen -W "$sheets" -- $2`)
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _cheat_autocomplete cheat
|
|
74
scripts/cheat.bash
Executable file
74
scripts/cheat.bash
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
# cheat(1) completion -*- shell-script -*-
|
||||||
|
|
||||||
|
# generate cheatsheet completions, optionally using `fzf`
|
||||||
|
_cheat_complete_cheatsheets()
|
||||||
|
{
|
||||||
|
if [[ "$CHEAT_USE_FZF" = true ]]; then
|
||||||
|
FZF_COMPLETION_TRIGGER='' _fzf_complete "--no-multi" "$@" < <(
|
||||||
|
cheat -l | tail -n +2 | cut -d' ' -f1
|
||||||
|
)
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -l | tail -n +2 | cut -d' ' -f1)" -- "$cur") )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# generate tag completions, optionally using `fzf`
|
||||||
|
_cheat_complete_tags()
|
||||||
|
{
|
||||||
|
if [ "$CHEAT_USE_FZF" = true ]; then
|
||||||
|
FZF_COMPLETION_TRIGGER='' _fzf_complete "--no-multi" "$@" < <(cheat -T)
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -T)" -- "$cur") )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# implement the `cheat` autocompletions
|
||||||
|
_cheat()
|
||||||
|
{
|
||||||
|
local cur prev words cword split
|
||||||
|
_init_completion -s || return
|
||||||
|
|
||||||
|
# complete options that are currently being typed: `--col` => `--colorize`
|
||||||
|
if [[ $cur == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W '$(_parse_help "$1" | sed "s/=//g")' -- "$cur") )
|
||||||
|
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# implement completions
|
||||||
|
case $prev in
|
||||||
|
--colorize|-c|\
|
||||||
|
--directories|-d|\
|
||||||
|
--init|\
|
||||||
|
--regex|-r|\
|
||||||
|
--search|-s|\
|
||||||
|
--tags|-T|\
|
||||||
|
--version|-v)
|
||||||
|
# noop the above, which should implement no completions
|
||||||
|
;;
|
||||||
|
--edit|-e)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--list|-l)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--path|-p)
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -d | cut -d':' -f1)" -- "$cur") )
|
||||||
|
;;
|
||||||
|
--rm)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--tag|-t)
|
||||||
|
_cheat_complete_tags
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$split && return
|
||||||
|
|
||||||
|
} &&
|
||||||
|
complete -F _cheat cheat
|
||||||
|
|
||||||
|
# ex: filetype=sh
|
@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This function enables you to choose a cheatsheet to view by selecting output
|
|
||||||
# from `cheat -l`. `source` it in your shell to enable it. (Consider renaming
|
|
||||||
# or aliasing it to something convenient.)
|
|
||||||
|
|
||||||
# Arguments passed to this function (like --color) will be passed to the second
|
|
||||||
# invokation of `cheat`.
|
|
||||||
function cheat-fzf {
|
|
||||||
eval `cheat -l | tail -n +2 | fzf | awk -v vars="$*" '{ print "cheat " $1 " -t " $3, vars }'`
|
|
||||||
}
|
|
Reference in New Issue
Block a user