Merge pull request #569 from chrisallenlane/dev

v4.0.0
This commit is contained in:
Chris Allen Lane 2020-06-25 19:05:37 -04:00 committed by GitHub
commit 4e9b2928b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 101 additions and 17 deletions

View File

@ -1,18 +1,20 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"os"
"text/tabwriter" "text/tabwriter"
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/display"
) )
// cmdDirectories lists the configured cheatpaths. // cmdDirectories lists the configured cheatpaths.
func cmdDirectories(opts map[string]interface{}, conf config.Config) { func cmdDirectories(opts map[string]interface{}, conf config.Config) {
// initialize a tabwriter to produce cleanly columnized output // initialize a tabwriter to produce cleanly columnized output
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) var out bytes.Buffer
w := tabwriter.NewWriter(&out, 0, 0, 1, ' ', 0)
// generate sorted, columnized output // generate sorted, columnized output
for _, path := range conf.Cheatpaths { for _, path := range conf.Cheatpaths {
@ -25,4 +27,5 @@ func cmdDirectories(opts map[string]interface{}, conf config.Config) {
// write columnized output to stdout // write columnized output to stdout
w.Flush() w.Flush()
display.Display(out.String(), conf)
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"os" "os"
"regexp" "regexp"
@ -9,6 +10,7 @@ import (
"text/tabwriter" "text/tabwriter"
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/display"
"github.com/cheat/cheat/internal/sheet" "github.com/cheat/cheat/internal/sheet"
"github.com/cheat/cheat/internal/sheets" "github.com/cheat/cheat/internal/sheets"
) )
@ -79,16 +81,19 @@ func cmdList(opts map[string]interface{}, conf config.Config) {
flattened = filtered flattened = filtered
} }
// exit early if no cheatsheets are available // return exit code 2 if no cheatsheets are available
if len(flattened) == 0 { if len(flattened) == 0 {
os.Exit(0) os.Exit(2)
} }
// initialize a tabwriter to produce cleanly columnized output // initialize a tabwriter to produce cleanly columnized output
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) var out bytes.Buffer
w := tabwriter.NewWriter(&out, 0, 0, 1, ' ', 0)
// write a header row
fmt.Fprintln(w, "title:\tfile:\ttags:")
// generate sorted, columnized output // generate sorted, columnized output
fmt.Fprintln(w, "title:\tfile:\ttags:")
for _, sheet := range flattened { for _, sheet := range flattened {
fmt.Fprintln(w, fmt.Sprintf( fmt.Fprintln(w, fmt.Sprintf(
"%s\t%s\t%s", "%s\t%s\t%s",
@ -100,4 +105,5 @@ func cmdList(opts map[string]interface{}, conf config.Config) {
// write columnized output to stdout // write columnized output to stdout
w.Flush() w.Flush()
display.Display(out.String(), conf)
} }

View File

@ -37,8 +37,8 @@ func cmdRemove(opts map[string]interface{}, conf config.Config) {
// fail early if the requested cheatsheet does not exist // fail early if the requested cheatsheet does not exist
sheet, ok := consolidated[cheatsheet] sheet, ok := consolidated[cheatsheet]
if !ok { if !ok {
fmt.Fprintln(os.Stderr, fmt.Sprintf("no cheatsheet found for '%s'.\n", cheatsheet)) fmt.Fprintln(os.Stderr, fmt.Sprintf("No cheatsheet found for '%s'.\n", cheatsheet))
os.Exit(1) os.Exit(2)
} }
// fail early if the sheet is read-only // fail early if the sheet is read-only

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/display"
"github.com/cheat/cheat/internal/sheet" "github.com/cheat/cheat/internal/sheet"
"github.com/cheat/cheat/internal/sheets" "github.com/cheat/cheat/internal/sheets"
) )
@ -45,7 +46,7 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
s, ok := consolidated[cheatsheet] s, ok := consolidated[cheatsheet]
if !ok { if !ok {
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet) fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
os.Exit(0) os.Exit(2)
} }
consolidated = map[string]sheet.Sheet{ consolidated = map[string]sheet.Sheet{
@ -87,12 +88,14 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
} }
// output the cheatsheet title // output the cheatsheet title
fmt.Printf("%s:\n", sheet.Title) out := fmt.Sprintf("%s:\n", sheet.Title)
// indent each line of content with two spaces // indent each line of content with two spaces
for _, line := range strings.Split(sheet.Text, "\n") { for _, line := range strings.Split(sheet.Text, "\n") {
fmt.Printf(" %s\n", line) out += fmt.Sprintf(" %s\n", line)
} }
fmt.Println("")
// display the output
display.Display(out, conf)
} }
} }

View File

@ -5,6 +5,7 @@ import (
"os" "os"
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/display"
"github.com/cheat/cheat/internal/sheets" "github.com/cheat/cheat/internal/sheets"
) )
@ -18,8 +19,12 @@ func cmdTags(opts map[string]interface{}, conf config.Config) {
os.Exit(1) os.Exit(1)
} }
// write sheet tags to stdout // assemble the output
out := ""
for _, tag := range sheets.Tags(cheatsheets) { for _, tag := range sheets.Tags(cheatsheets) {
fmt.Println(tag) out += fmt.Sprintln(tag)
} }
// display the output
display.Display(out, conf)
} }

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/cheat/cheat/internal/config" "github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/display"
"github.com/cheat/cheat/internal/sheets" "github.com/cheat/cheat/internal/sheets"
) )
@ -38,7 +39,7 @@ func cmdView(opts map[string]interface{}, conf config.Config) {
sheet, ok := consolidated[cheatsheet] sheet, ok := consolidated[cheatsheet]
if !ok { if !ok {
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet) fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
os.Exit(0) os.Exit(2)
} }
// apply colorization if requested // apply colorization if requested
@ -47,5 +48,5 @@ func cmdView(opts map[string]interface{}, conf config.Config) {
} }
// display the cheatsheet // display the cheatsheet
fmt.Print(sheet.Text) display.Display(sheet.Text, conf)
} }

View File

@ -17,7 +17,7 @@ import (
"github.com/cheat/cheat/internal/installer" "github.com/cheat/cheat/internal/installer"
) )
const version = "3.10.1" const version = "4.0.0"
func main() { func main() {

View File

@ -23,6 +23,9 @@ style: monokai
# One of: "terminal", "terminal256", "terminal16m" # One of: "terminal", "terminal256", "terminal16m"
formatter: terminal16m formatter: terminal16m
# Through which pager should output be piped? (Unset this key for no pager.)
pager: less -FRX
# The paths at which cheatsheets are available. Tags associated with a cheatpath # The paths at which cheatsheets are available. Tags associated with a cheatpath
# are automatically attached to all cheatsheets residing on that path. # are automatically attached to all cheatsheets residing on that path.
# #

View File

@ -14,6 +14,9 @@ style: monokai
# One of: "terminal", "terminal256", "terminal16m" # One of: "terminal", "terminal256", "terminal16m"
formatter: terminal16m formatter: terminal16m
# Through which pager should output be piped? (Unset this key for no pager.)
pager: less -FRX
# The paths at which cheatsheets are available. Tags associated with a cheatpath # The paths at which cheatsheets are available. Tags associated with a cheatpath
# are automatically attached to all cheatsheets residing on that path. # are automatically attached to all cheatsheets residing on that path.
# #

View File

@ -203,6 +203,13 @@ If set, autocompletion scripts will attempt to integrate with
\f[B]fzf\f[]. \f[B]fzf\f[].
.RS .RS
.RE .RE
.SH RETURN VALUES
.IP "0." 3
Successful termination
.IP "1." 3
Application error
.IP "2." 3
Cheatsheet(s) not found
.SH BUGS .SH BUGS
.PP .PP
See GitHub issues: <https://github.com/cheat/cheat/issues> See GitHub issues: <https://github.com/cheat/cheat/issues>

View File

@ -163,6 +163,15 @@ set, all other config paths will be ignored.
: If set, autocompletion scripts will attempt to integrate with **fzf**. : If set, autocompletion scripts will attempt to integrate with **fzf**.
RETURN VALUES
=============
0. Successful termination
1. Application error
2. Cheatsheet(s) not found
BUGS BUGS
==== ====

View File

@ -5,6 +5,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
cp "github.com/cheat/cheat/internal/cheatpath" cp "github.com/cheat/cheat/internal/cheatpath"
@ -19,6 +20,7 @@ type Config struct {
Cheatpaths []cp.Cheatpath `yaml:"cheatpaths"` Cheatpaths []cp.Cheatpath `yaml:"cheatpaths"`
Style string `yaml:"style"` Style string `yaml:"style"`
Formatter string `yaml:"formatter"` Formatter string `yaml:"formatter"`
Pager string `yaml:"pager"`
} }
// New returns a new Config struct // New returns a new Config struct
@ -111,5 +113,10 @@ func New(opts map[string]interface{}, confPath string, resolve bool) (Config, er
conf.Formatter = "terminal16m" conf.Formatter = "terminal16m"
} }
// if a pager was not provided, set a default
if strings.TrimSpace(conf.Pager) == "" {
conf.Pager = ""
}
return conf, nil return conf, nil
} }

View File

@ -0,0 +1,37 @@
package display
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/cheat/cheat/internal/config"
)
// Display writes output either directly to stdout, or through a pager,
// depending upon configuration.
func Display(out string, conf config.Config) {
// if no pager was configured, print the output to stdout and exit
if conf.Pager == "" {
fmt.Print(out)
os.Exit(0)
}
// otherwise, pipe output through the pager
parts := strings.Split(conf.Pager, " ")
pager := parts[0]
args := parts[1:]
// run the pager
cmd := exec.Command(pager, args...)
cmd.Stdin = strings.NewReader(out)
cmd.Stdout = os.Stdout
// handle errors
err := cmd.Run()
if err != nil {
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to write to pager: %v", err))
os.Exit(1)
}
}