mirror of
https://github.com/cheat/cheat.git
synced 2025-09-04 02:58:29 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
e08a4f3cec | |||
d6ebe0799d | |||
51aaaf3423 | |||
197ff58796 | |||
b8f512aae8 | |||
e7a1a296e3 | |||
f7c093bec0 | |||
c47b7f81aa | |||
52081b97ac | |||
1dda796e7c | |||
67469b0afa | |||
4f8431a600 | |||
5301442f7c | |||
cd45efcdec | |||
c31786fc5b | |||
934c36ad77 | |||
2c0099c28a | |||
749173f1f6 | |||
33e33dc7b7 | |||
201cd1d629 |
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Submit a bug report
|
||||||
|
title: ''
|
||||||
|
labels: 'bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thanks for submitting a bug report. Please provide the following information:
|
||||||
|
|
||||||
|
**A description of the problem**
|
||||||
|
Describe the problem here.
|
||||||
|
|
||||||
|
**cheat version info**
|
||||||
|
Please paste the output of `cheat -v` here.
|
||||||
|
|
||||||
|
**cheat configuration info**
|
||||||
|
If your bug pertains to how cheatsheets are loaded and/or displayed, please
|
||||||
|
paste here the following information:
|
||||||
|
|
||||||
|
1. The output of `cheat -d`
|
||||||
|
2. The contents of your `conf.yml` file
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: 'enhancement'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
@ -178,11 +178,11 @@ To search (by regex) for cheatsheets that contain an IP address:
|
|||||||
cheat -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
```
|
```
|
||||||
|
|
||||||
Flags may be combined in inuitive ways. Example: to search sheets on the
|
Flags may be combined in intuitive ways. Example: to search sheets on the
|
||||||
"personal" cheatpath that are tagged with "networking" and match a regex:
|
"personal" cheatpath that are tagged with "networking" and match a regex:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cheat -p personal -t networking -s --regex '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -p personal -t networking --regex -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "3.0.3"
|
const version = "3.0.5"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// initialize the configs
|
// initialize the configs
|
||||||
conf, err := config.New(opts, confpath)
|
conf, err := config.New(opts, confpath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -32,9 +32,9 @@ formatter: terminal16m
|
|||||||
# "upstream" cheatsheets.
|
# "upstream" cheatsheets.
|
||||||
#
|
#
|
||||||
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
||||||
# Cheatsheets may be filtered via 'cheat -f <tag>' in combination with other
|
# Cheatsheets may be filtered via 'cheat -t <tag>' in combination with other
|
||||||
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
||||||
# 'community' rather than your own, you can use: cheat tar -f community
|
# 'community' rather than your own, you can use: cheat tar -t community
|
||||||
cheatpaths:
|
cheatpaths:
|
||||||
|
|
||||||
# Paths that come earlier are considered to be the most "global", and will
|
# Paths that come earlier are considered to be the most "global", and will
|
||||||
|
@ -23,9 +23,9 @@ formatter: terminal16m
|
|||||||
# "upstream" cheatsheets.
|
# "upstream" cheatsheets.
|
||||||
#
|
#
|
||||||
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
||||||
# Cheatsheets may be filtered via 'cheat -f <tag>' in combination with other
|
# Cheatsheets may be filtered via 'cheat -t <tag>' in combination with other
|
||||||
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
||||||
# 'community' rather than your own, you can use: cheat tar -f community
|
# 'community' rather than your own, you can use: cheat tar -t community
|
||||||
cheatpaths:
|
cheatpaths:
|
||||||
|
|
||||||
# Paths that come earlier are considered to be the most "global", and will
|
# Paths that come earlier are considered to be the most "global", and will
|
||||||
|
3
go.mod
3
go.mod
@ -9,7 +9,6 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.10
|
github.com/mattn/go-isatty v0.0.10
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
|
||||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.2.4
|
gopkg.in/yaml.v2 v2.2.4
|
||||||
)
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -50,8 +50,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1 h1:lA+aPRvltlx2fwv/BnxyYSDQo3pIeqzHgMO5GvK0T9E=
|
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1/go.mod h1:deJrtusCTptAW4EUn5vBLpl3dhNqPqUwEjWJz5UNxpQ=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
|
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
cp "github.com/cheat/cheat/internal/cheatpath"
|
cp "github.com/cheat/cheat/internal/cheatpath"
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Config struct
|
// New returns a new Config struct
|
||||||
func New(opts map[string]interface{}, confPath string) (Config, error) {
|
func New(opts map[string]interface{}, confPath string, resolve bool) (Config, error) {
|
||||||
|
|
||||||
// read the config file
|
// read the config file
|
||||||
buf, err := ioutil.ReadFile(confPath)
|
buf, err := ioutil.ReadFile(confPath)
|
||||||
@ -38,14 +39,34 @@ func New(opts map[string]interface{}, confPath string) (Config, error) {
|
|||||||
return Config{}, fmt.Errorf("could not unmarshal yaml: %v", err)
|
return Config{}, fmt.Errorf("could not unmarshal yaml: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand ~ in config paths
|
// process cheatpaths
|
||||||
for i, cheatpath := range conf.Cheatpaths {
|
for i, cheatpath := range conf.Cheatpaths {
|
||||||
|
|
||||||
|
// expand ~ in config paths
|
||||||
expanded, err := homedir.Expand(cheatpath.Path)
|
expanded, err := homedir.Expand(cheatpath.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Config{}, fmt.Errorf("failed to expand ~: %v", err)
|
return Config{}, fmt.Errorf("failed to expand ~: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// follow symlinks
|
||||||
|
//
|
||||||
|
// NB: `resolve` is an ugly kludge that exists for the sake of unit-tests.
|
||||||
|
// It's necessary because `EvalSymlinks` will error if the symlink points
|
||||||
|
// to a non-existent location on the filesystem. When unit-testing,
|
||||||
|
// however, we don't want to have dependencies on the filesystem. As such,
|
||||||
|
// `resolve` is a switch that allows us to turn off symlink resolution when
|
||||||
|
// running the config tests.
|
||||||
|
if resolve {
|
||||||
|
expanded, err = filepath.EvalSymlinks(expanded)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, fmt.Errorf(
|
||||||
|
"failed to resolve symlink: %s, %v",
|
||||||
|
expanded,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conf.Cheatpaths[i].Path = expanded
|
conf.Cheatpaths[i].Path = expanded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
func TestConfigSuccessful(t *testing.T) {
|
func TestConfigSuccessful(t *testing.T) {
|
||||||
|
|
||||||
// initialize a config
|
// initialize a config
|
||||||
conf, err := New(map[string]interface{}{}, mock.Path("conf/conf.yml"))
|
conf, err := New(map[string]interface{}{}, mock.Path("conf/conf.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to parse config file: %v", err)
|
t.Errorf("failed to parse config file: %v", err)
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func TestConfigSuccessful(t *testing.T) {
|
|||||||
func TestConfigFailure(t *testing.T) {
|
func TestConfigFailure(t *testing.T) {
|
||||||
|
|
||||||
// attempt to read a non-existent config file
|
// attempt to read a non-existent config file
|
||||||
_, err := New(map[string]interface{}{}, "/does-not-exit")
|
_, err := New(map[string]interface{}{}, "/does-not-exit", false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("failed to error on unreadable config")
|
t.Errorf("failed to error on unreadable config")
|
||||||
}
|
}
|
||||||
@ -84,14 +84,14 @@ func TestEmptyEditor(t *testing.T) {
|
|||||||
os.Setenv("EDITOR", "")
|
os.Setenv("EDITOR", "")
|
||||||
|
|
||||||
// initialize a config
|
// initialize a config
|
||||||
conf, err := New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err := New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("failed to return an error on empty editor")
|
t.Errorf("failed to return an error on empty editor")
|
||||||
}
|
}
|
||||||
|
|
||||||
// set editor, and assert that it is respected
|
// set editor, and assert that it is respected
|
||||||
os.Setenv("EDITOR", "foo")
|
os.Setenv("EDITOR", "foo")
|
||||||
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to init configs: %v", err)
|
t.Errorf("failed to init configs: %v", err)
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ func TestEmptyEditor(t *testing.T) {
|
|||||||
|
|
||||||
// set visual, and assert that it overrides editor
|
// set visual, and assert that it overrides editor
|
||||||
os.Setenv("VISUAL", "bar")
|
os.Setenv("VISUAL", "bar")
|
||||||
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to init configs: %v", err)
|
t.Errorf("failed to init configs: %v", err)
|
||||||
}
|
}
|
||||||
|
34
internal/frontmatter/frontmatter.go
Normal file
34
internal/frontmatter/frontmatter.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package frontmatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frontmatter encapsulates cheatsheet frontmatter data
|
||||||
|
type Frontmatter struct {
|
||||||
|
Tags []string
|
||||||
|
Syntax string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses cheatsheet frontmatter
|
||||||
|
func Parse(markdown string) (string, Frontmatter, error) {
|
||||||
|
|
||||||
|
// specify the frontmatter delimiter
|
||||||
|
delim := "---"
|
||||||
|
|
||||||
|
// initialize a frontmatter struct
|
||||||
|
var fm Frontmatter
|
||||||
|
|
||||||
|
// if the markdown does not contain frontmatter, pass it through unmodified
|
||||||
|
if !strings.HasPrefix(markdown, delim) {
|
||||||
|
return strings.TrimSpace(markdown), fm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, split the frontmatter and cheatsheet text
|
||||||
|
parts := strings.SplitN(markdown, delim, 3)
|
||||||
|
err := yaml.Unmarshal([]byte(parts[1]), &fm)
|
||||||
|
|
||||||
|
return strings.TrimSpace(parts[2]), fm, err
|
||||||
|
}
|
71
internal/frontmatter/frontmatter_test.go
Normal file
71
internal/frontmatter/frontmatter_test.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package frontmatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestHasFrontmatter asserts that markdown is properly parsed when it contains
|
||||||
|
// frontmatter
|
||||||
|
func TestHasFrontmatter(t *testing.T) {
|
||||||
|
|
||||||
|
// stub our cheatsheet content
|
||||||
|
markdown := `---
|
||||||
|
syntax: go
|
||||||
|
tags: [ test ]
|
||||||
|
---
|
||||||
|
To foo the bar: baz`
|
||||||
|
|
||||||
|
// parse the frontmatter
|
||||||
|
text, fm, err := Parse(markdown)
|
||||||
|
|
||||||
|
// assert expectations
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to parse markdown: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "To foo the bar: baz"
|
||||||
|
if text != want {
|
||||||
|
t.Errorf("failed to parse text: want: %s, got: %s", want, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
want = "go"
|
||||||
|
if fm.Syntax != want {
|
||||||
|
t.Errorf("failed to parse syntax: want: %s, got: %s", want, fm.Syntax)
|
||||||
|
}
|
||||||
|
|
||||||
|
want = "test"
|
||||||
|
if fm.Tags[0] != want {
|
||||||
|
t.Errorf("failed to parse tags: want: %s, got: %s", want, fm.Tags[0])
|
||||||
|
}
|
||||||
|
if len(fm.Tags) != 1 {
|
||||||
|
t.Errorf("failed to parse tags: want: len 0, got: len %d", len(fm.Tags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHasFrontmatter asserts that markdown is properly parsed when it does not
|
||||||
|
// contain frontmatter
|
||||||
|
func TestHasNoFrontmatter(t *testing.T) {
|
||||||
|
|
||||||
|
// stub our cheatsheet content
|
||||||
|
markdown := "To foo the bar: baz"
|
||||||
|
|
||||||
|
// parse the frontmatter
|
||||||
|
text, fm, err := Parse(markdown)
|
||||||
|
|
||||||
|
// assert expectations
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to parse markdown: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if text != markdown {
|
||||||
|
t.Errorf("failed to parse text: want: %s, got: %s", markdown, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fm.Syntax != "" {
|
||||||
|
t.Errorf("failed to parse syntax: want: '', got: %s", fm.Syntax)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fm.Tags) != 0 {
|
||||||
|
t.Errorf("failed to parse tags: want: len 0, got: len %d", len(fm.Tags))
|
||||||
|
}
|
||||||
|
}
|
@ -4,17 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tj/front"
|
"github.com/cheat/cheat/internal/frontmatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// frontmatter is an un-exported helper struct used in parsing cheatsheets
|
|
||||||
type frontmatter struct {
|
|
||||||
Tags []string
|
|
||||||
Syntax string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sheet encapsulates sheet information
|
// Sheet encapsulates sheet information
|
||||||
type Sheet struct {
|
type Sheet struct {
|
||||||
Title string
|
Title string
|
||||||
@ -39,9 +32,8 @@ func New(
|
|||||||
return Sheet{}, fmt.Errorf("failed to read file: %s, %v", path, err)
|
return Sheet{}, fmt.Errorf("failed to read file: %s, %v", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the front-matter
|
// parse the cheatsheet frontmatter
|
||||||
var fm frontmatter
|
text, fm, err := frontmatter.Parse(string(markdown))
|
||||||
text, err := front.Unmarshal(markdown, &fm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Sheet{}, fmt.Errorf("failed to parse front-matter: %v", err)
|
return Sheet{}, fmt.Errorf("failed to parse front-matter: %v", err)
|
||||||
}
|
}
|
||||||
@ -56,7 +48,7 @@ func New(
|
|||||||
return Sheet{
|
return Sheet{
|
||||||
Title: title,
|
Title: title,
|
||||||
Path: path,
|
Path: path,
|
||||||
Text: strings.TrimSpace(string(text)) + "\n",
|
Text: text + "\n",
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
Syntax: fm.Syntax,
|
Syntax: fm.Syntax,
|
||||||
ReadOnly: readOnly,
|
ReadOnly: readOnly,
|
||||||
|
@ -48,8 +48,13 @@ func Load(cheatpaths []cp.Cheatpath) ([]map[string]sheet.Sheet, error) {
|
|||||||
"/",
|
"/",
|
||||||
)
|
)
|
||||||
|
|
||||||
// ignore dotfiles. Otherwise, we'll likely load .git/*
|
// ignore hidden files and directories. Otherwise, we'll likely load
|
||||||
if strings.HasPrefix(title, ".") {
|
// .git/* and .DS_Store.
|
||||||
|
//
|
||||||
|
// NB: this is still somewhat brittle in that it will miss files
|
||||||
|
// contained within hidden directories in the middle of a path, though
|
||||||
|
// that should not realistically occur.
|
||||||
|
if strings.HasPrefix(title, ".") || strings.HasPrefix(info.Name(), ".") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
scripts/cheat-autocompletion.bash
Executable file
9
scripts/cheat-autocompletion.bash
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
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
|
11
scripts/cheat-autocompletion.fish
Executable file
11
scripts/cheat-autocompletion.fish
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
complete -c cheat -f -a "(cheat -l | tail -n +2 | cut -d ' ' -f 1)"
|
||||||
|
complete -c cheat -l init -d "Write a default config file to stdout"
|
||||||
|
complete -c cheat -s c -l colorize -d "Colorize output"
|
||||||
|
complete -c cheat -s d -l directories -d "List cheatsheet directories"
|
||||||
|
complete -c cheat -s e -l edit -x -a "(cheat -l | tail -n +2 | cut -d ' ' -f 1)" -d "Edit cheatsheet"
|
||||||
|
complete -c cheat -s l -l list -d "List cheatsheets"
|
||||||
|
complete -c cheat -s p -l path -x -a "(cheat -d | cut -d ':' -f 1)" -d "Return only sheets found on given path"
|
||||||
|
complete -c cheat -s r -l regex -d "Treat search phrase as a regex"
|
||||||
|
complete -c cheat -s s -l search -x -d "Search cheatsheets for given phrase"
|
||||||
|
complete -c cheat -s t -l tag -x -a "(cheat -l | tail -n +2 | rev | cut -d ' ' -f 1 | rev | sed 's/,/\n/g;/^\$/d' | sort -u)" -d "Return only sheets matching the given tag"
|
||||||
|
complete -c cheat -s v -l version -d "Print the version number"
|
16
vendor/github.com/tj/front/Readme.md
generated
vendored
16
vendor/github.com/tj/front/Readme.md
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
# Front
|
|
||||||
|
|
||||||
Frontmatter unmarshaller, couldn't find one without a weird API.
|
|
||||||
|
|
||||||
## Badges
|
|
||||||
|
|
||||||
[](https://godoc.org/github.com/tj/front)
|
|
||||||

|
|
||||||

|
|
||||||
[](https://apex.sh/ping/)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
> [tjholowaychuk.com](http://tjholowaychuk.com) ·
|
|
||||||
> GitHub [@tj](https://github.com/tj) ·
|
|
||||||
> Twitter [@tjholowaychuk](https://twitter.com/tjholowaychuk)
|
|
24
vendor/github.com/tj/front/front.go
generated
vendored
24
vendor/github.com/tj/front/front.go
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
// Package front provides YAML frontmatter unmarshalling.
|
|
||||||
package front
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Delimiter.
|
|
||||||
var delim = []byte("---")
|
|
||||||
|
|
||||||
// Unmarshal parses YAML frontmatter and returns the content. When no
|
|
||||||
// frontmatter delimiters are present the original content is returned.
|
|
||||||
func Unmarshal(b []byte, v interface{}) (content []byte, err error) {
|
|
||||||
if !bytes.HasPrefix(b, delim) {
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := bytes.SplitN(b, delim, 3)
|
|
||||||
content = parts[2]
|
|
||||||
err = yaml.Unmarshal(parts[1], v)
|
|
||||||
return
|
|
||||||
}
|
|
Reference in New Issue
Block a user