Compare commits

..

35 Commits
3.5.0 ... 3.9.0

Author SHA1 Message Date
c4dd3b52fd Merge pull request #554 from chrisallenlane/master
v3.9.0
2020-04-07 18:59:18 -04:00
e8a0ea0dc3 chore(version): bump version to 3.9.0 2020-04-07 18:50:00 -04:00
992ee66a56 Merge branch 'add-homebrew-release-flow' of https://github.com/chenrui333/cheat into v3.9.0 2020-04-07 18:48:57 -04:00
c9840c2d6f docs(autocompletion): update autocompletion docs
Update the autocompletion documentation (in `README` and `man` page) to
include information about configuring `zsh` autocompletion script.
2020-04-07 18:47:35 -04:00
bd53768f67 chore(zsh): set execute perm on cheat.zsh
Set execute permission on the `zsh` autocompletion script.
2020-04-07 18:41:00 -04:00
8092687956 change taglist and pathlist to local variable. 2020-04-07 14:56:34 +08:00
16ade50672 add complete script for zsh. 2020-04-03 15:34:01 +08:00
62c80d76eb Automate homebrew release flow 2020-03-24 21:21:54 -04:00
3e67eaa3b7 Merge pull request #546 from chrisallenlane/issue-272
docs(man): implement manpage
2020-03-24 20:55:57 -04:00
38b13655fe chore(version): bump version to 3.8.0 2020-03-24 20:54:40 -04:00
749d5c1182 docs(man): implement manpage
- Implement `make man` to generate a manpage

- Change verb tense in `make` help text
2020-03-24 20:46:48 -04:00
521f83377c Merge pull request #545 from chrisallenlane/issue-544
fix(frontmatter): resolve #544
2020-03-11 19:03:06 -04:00
b15ff10537 chore(version): bump version to 3.7.1 2020-03-11 18:55:59 -04:00
5288bd0c1c fix(frontmatter): resolve issue #544
- Fix error in `frontmatter.Parse` which would cause a `panic` when
  encountering malformed frontmatter

- Add a unit-test to cover the above
2020-03-11 18:54:46 -04:00
bddbee4158 fix(logging): improve sheets load logging
Improve logging in `sheets.Load`:

- Make error verbage consistant with verbiage elsewhere

- Add more information to logging statements
2020-03-11 18:51:06 -04:00
ce27cf2cc0 chore(version): bump version to 3.7.0 2020-03-06 20:19:31 -05:00
5733b1d6d4 chore(vendor): update vendor dependencies 2020-03-06 20:18:41 -05:00
2d221050d8 Merge branch '1-14' into 3.7.0 2020-03-06 20:17:54 -05:00
ce37b670c7 feat(installer): implement "installer"
Squashed commit of the following:

commit 5c322e79b7
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Fri Mar 6 19:56:56 2020 -0500

    docs(README): update the `README`

    Update the `README` to document the improved config-generation
    mechanism.

commit 803e1f014c
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Fri Mar 6 19:19:49 2020 -0500

    feat(config-init): platform-specific pathing

    Update `--init` subcommand to rely upon the same platform-detection
    intelligence that was previously implemented by the "installer".

    The installer and `--init` should now produce identical config files.

commit 99c48097e2
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Fri Mar 6 18:26:33 2020 -0500

    feat(installer): platform-correct config templating

    Modify the "installer" to populate cheatpaths with sensible defaults
    based on the detection of the user's operating system and environment.

commit 8e1580ff5a
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Thu Mar 5 20:19:58 2020 -0500

    fix(tests): fix `config.Paths` tests

    Refactor `config.Paths` (by externalizing a call to `homedir.Dir`) to
    decouple it from filesystem paths, thus facilitating cleaner unit-tests.

commit a08dca70d9
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Thu Mar 5 18:14:27 2020 -0500

    feat(installer): default path selection

    Modify the installer to improve default config and cheatsheet path
    selection.

commit e15bc6c966
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Thu Mar 5 17:49:50 2020 -0500

    fix(typo): correct comment typo in `main.go`

commit efd09575df
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Thu Mar 5 17:46:49 2020 -0500

    feat(config): refactor config path detection

    Previously, failing other checks, on Unix and BSD systems,
    `config.Paths` would attempt to compute the user's home directory by
    reading the `HOME` environment variable.

    This change deprecates that approach with a call to `homedir.Dir`, which
    is used elsewhere throughout the application.

commit ec10244ebe
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Thu Mar 5 17:15:28 2020 -0500

    chore(installer): delete unused file

    Delete `installer/installer.go`, which (in hindsight) was unnecessary.

commit ebd9ec6287
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Wed Mar 4 19:31:13 2020 -0500

    wip(installer): stub experimental "installer"

    Stubs out an experimental "installer" that will help new users to
    quickly configure `cheat`.

commit ecac5a0971
Author: Chris Lane <chris@chris-allen-lane.com>
Date:   Wed Mar 4 19:30:12 2020 -0500

    chore(dependencies): updates vendored dependencies
2020-03-06 20:17:26 -05:00
47a9eeb4fd go mod vendor 2020-03-03 18:28:13 -05:00
be56c9cf0c Bump golang to v1.14 2020-03-03 18:27:31 -05:00
7be57cb01c Merge pull request #540 from chrisallenlane/master
fix: README and Makefil
2020-02-26 19:29:04 -05:00
8453af8601 fix(Makefile): build targets
Adds missing dependencies to the `build` and `install` targets.
2020-02-26 19:21:07 -05:00
6e388c3693 fix(README): typo fix
Fixes a bad link to the completion scripts in the `README`.
2020-02-26 19:20:24 -05:00
b13246978a Merge pull request #538 from chrisallenlane/improved-search
feat(search): issue #260
2020-02-15 18:07:40 -05:00
a39d36cd34 chore: bumps version to 3.6.0 2020-02-15 16:13:33 -05:00
87cba04ff2 chore: DRY out colorization code
Creates a `sheet.Colorize` method that DRYs out code that was duplicated
among `cmd_search` and `cmd_view`.
2020-02-15 16:11:15 -05:00
bc623da74b feat: issue #260
Dramatically improves the usefulness of `--search` by outputting
"chunked" results. This removes the need (usually) to search and then
manually open a cheatsheet.
2020-02-15 15:56:25 -05:00
a6c25d4b9c feat: --search improvements
- Deprecates the `Match` struct

- Applies syntax highlighting to search results output in a manner
  consistent with the 'View' output

- Refactors search to move colorization functionality outside of its
  concern
2020-02-15 14:42:06 -05:00
e24ac2b385 chore: deprecates line numbers in search
Removes line numbers from search result output as part of the
refactoring effort.
2020-02-15 10:11:25 -05:00
e0c35a74d4 chore: removes colorization from search
Deprecates `mgutz/ansi` and removes colorization from search as a first
step toward improving the functionality.
2020-02-15 10:01:44 -05:00
3e4c1818a9 feat: single-sheet searching
`--search` will now honor the `<cheatsheet>` argument, making it
possible to constrain a search to a single cheatsheet.
2020-02-15 06:38:57 -05:00
7b4a268ebd fix: resolves #301
Fixes an issue whereby `cheat` would crash when `$EDITOR` (or
equivalent) contained arguments.
2020-02-02 15:56:18 -05:00
f7183aa17a Merge pull request #536 from chrisallenlane/issue-301
fix: issue #301
2020-02-02 15:54:47 -05:00
1ce6c29e6a fix: issue #301
Attempts to resolve issue #301, whereby `cheat` fails if `$EDITOR` (or
equivalent) contains flags.
2020-02-02 15:48:45 -05:00
113 changed files with 14097 additions and 91928 deletions

17
.github/workflows/homebrew.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: homebrew
on:
push:
tags: '*'
jobs:
homebrew:
name: Bump Homebrew formula
runs-on: ubuntu-latest
steps:
- uses: mislav/bump-homebrew-formula-action@v1
with:
# A PR will be sent to github.com/Homebrew/homebrew-core to update this formula:
formula-name: cheat
env:
COMMITTER_TOKEN: ${{ secrets.COMMITTER_TOKEN }}

View File

@ -1,7 +1,7 @@
language: go
go:
- 1.13.x
- 1.14.x
os:
- linux

View File

@ -11,7 +11,9 @@ GO := go
GREP := grep
GZIP := gzip --best
LINT := revive
MAN := man
MKDIR := mkdir -p
PANDOC := pandoc
RM := rm
SCC := scc
SED := sed
@ -32,16 +34,16 @@ releases := \
$(dist_dir)/cheat-linux-arm7 \
$(dist_dir)/cheat-windows-amd64.exe
## build: builds an executable for your architecture
## build: build an executable for your architecture
.PHONY: build
build: $(dist_dir) clean generate
build: $(dist_dir) clean vendor generate man
$(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir)
## build-release: builds release executables
## build-release: build release executables
.PHONY: build-release
build-release: $(releases)
## ci: builds a "release" executable for the current architecture (used in ci)
## ci: build a "release" executable for the current architecture (used in ci)
.PHONY: ci
ci: | setup prepare build
@ -83,75 +85,81 @@ $(dist_dir):
generate:
$(GO) generate $(cmd_dir)
## install: builds and installs cheat on your PATH
## install: build and install cheat on your PATH
.PHONY: install
install:
install: build
$(GO) install $(BUILD_FLAGS) $(GOBIN) $(cmd_dir)
## clean: removes compiled executables
## clean: remove compiled executables
.PHONY: clean
clean: $(dist_dir)
$(RM) -f $(dist_dir)/*
## distclean: removes the tags file
## distclean: remove the tags file
.PHONY: distclean
distclean:
$(RM) -f tags
## setup: installs revive (linter) and scc (sloc tool)
## setup: install revive (linter) and scc (sloc tool)
.PHONY: setup
setup:
GO111MODULE=off $(GO) get -u github.com/boyter/scc github.com/mgechev/revive
## sloc: counts "semantic lines of code"
## sloc: count "semantic lines of code"
.PHONY: sloc
sloc:
$(SCC) --exclude-dir=vendor
## tags: builds a tags file
## tags: build a tags file
.PHONY: tags
tags:
$(CTAGS) -R --exclude=vendor --languages=go
## vendor: downloads, tidies, and verifies dependencies
## man: build a man page
# NB: pandoc may not be installed, so we're ignoring this error on failure
.PHONY: man
man:
-$(PANDOC) -s -t man doc/cheat.1.md -o doc/cheat.1
## vendor: download, tidy, and verify dependencies
.PHONY: vendor
vendor:
$(GO) mod vendor && $(GO) mod tidy && $(GO) mod verify
## fmt: runs go fmt
## fmt: run go fmt
.PHONY: fmt
fmt:
$(GO) fmt ./...
## lint: lints go source files
## lint: lint go source files
.PHONY: lint
lint: vendor
$(LINT) -exclude vendor/... ./...
## vet: vets go source files
## vet: vet go source files
.PHONY: vet
vet:
$(GO) vet ./...
## test: runs unit-tests
## test: run unit-tests
.PHONY: test
test:
$(GO) test ./...
## coverage: generates a test coverage report
## coverage: generate 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: format, lint, vet, vendor, and run unit-tests
.PHONY: check
check: | vendor fmt lint vet test
.PHONY: prepare
prepare: | $(dist_dir) clean generate vendor fmt lint vet test
## help: displays this help text
## help: display this help text
.PHONY: help
help:
@$(CAT) $(makefile) | \

View File

@ -51,7 +51,9 @@ Installing
Configuring
-----------
### conf.yml ###
`cheat` is configured by a YAML file that can be generated with `cheat --init`:
`cheat` is configured by a YAML file that will be auto-generated on first run.
Should you need to create a config file manually, you can do
so via:
```sh
mkdir -p ~/.config/cheat && cheat --init > ~/.config/cheat/conf.yml
@ -89,7 +91,8 @@ const squares = [1, 2, 3, 4].map(x => x * x);
```
The `cheat` executable includes no cheatsheets, but [community-sourced
cheatsheets are available][cheatsheets].
cheatsheets are available][cheatsheets]. You will be asked if you would like to
install the community-sourced cheatsheets the first time you run `cheat`.
Cheatpaths
@ -193,19 +196,18 @@ cheat -p personal -t networking --regex -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
Advanced Usage
--------------
Shell autocompletion is currently available for the `bash` and `fish` shells.
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.)
Shell autocompletion is currently available for `bash`, `fish`, and `zsh`. Copy
the relevant [completion script][completions] 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:
[fzf][]. 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
[bash]: https://github.com/cheat/cheat/blob/master/scripts/fzf.bash
[cheatsheets]: https://github.com/cheat/cheatsheets
[completions]: https://github.com/cheat/cheat/tree/master/scripts
[fzf]: https://github.com/junegunn/fzf

View File

@ -99,8 +99,15 @@ func cmdEdit(opts map[string]interface{}, conf config.Config) {
}
}
// split `conf.Editor` into parts to separate the editor's executable from
// any arguments it may have been passed. If this is not done, the nearby
// call to `exec.Command` will fail.
parts := strings.Fields(conf.Editor)
editor := parts[0]
args := append(parts[1:], editpath)
// edit the cheatsheet
cmd := exec.Command(conf.Editor, editpath)
cmd := exec.Command(editor, args...)
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr

View File

@ -2,9 +2,56 @@ package main
import (
"fmt"
"os"
"path"
"runtime"
"strings"
"github.com/mitchellh/go-homedir"
"github.com/cheat/cheat/internal/config"
)
// cmdInit displays an example config file.
func cmdInit() {
fmt.Println(configs())
// get the user's home directory
home, err := homedir.Dir()
if err != nil {
fmt.Fprintf(os.Stderr, "failed to get user home directory: %v\n", err)
os.Exit(1)
}
// read the envvars into a map of strings
envvars := map[string]string{}
for _, e := range os.Environ() {
pair := strings.SplitN(e, "=", 2)
envvars[pair[0]] = pair[1]
}
// load the config template
configs := configs()
// identify the os-specifc paths at which configs may be located
confpaths, err := config.Paths(runtime.GOOS, home, envvars)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to read config paths: %v\n", err)
os.Exit(1)
}
// determine the appropriate paths for config data and (optional) community
// cheatsheets based on the user's platform
confpath := confpaths[0]
confdir := path.Dir(confpath)
// create paths for community and personal cheatsheets
community := path.Join(confdir, "/cheatsheets/community")
personal := path.Join(confdir, "/cheatsheets/personal")
// template the above paths into the default configs
configs = strings.Replace(configs, "COMMUNITY_PATH", community, -1)
configs = strings.Replace(configs, "PERSONAL_PATH", personal, -1)
// output the templated configs
fmt.Println(configs)
}

View File

@ -7,6 +7,7 @@ import (
"strings"
"github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/sheet"
"github.com/cheat/cheat/internal/sheets"
)
@ -35,6 +36,23 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
// local cheatsheets)
consolidated := sheets.Consolidate(cheatsheets)
// if <cheatsheet> was provided, search that single sheet only
if opts["<cheatsheet>"] != nil {
cheatsheet := opts["<cheatsheet>"].(string)
// assert that the cheatsheet exists
s, ok := consolidated[cheatsheet]
if !ok {
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
os.Exit(0)
}
consolidated = map[string]sheet.Sheet{
cheatsheet: s,
}
}
// sort the cheatsheets alphabetically, and search for matches
for _, sheet := range sheets.Sort(consolidated) {
@ -53,17 +71,28 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
os.Exit(1)
}
// search the sheet
matches := sheet.Search(reg, conf.Color(opts))
// `Search` will return text entries that match the search terms. We're
// using it here to overwrite the prior cheatsheet Text, filtering it to
// only what is relevant
sheet.Text = sheet.Search(reg)
// display the results
if len(matches) > 0 {
fmt.Printf("%s:\n", sheet.Title)
for _, m := range matches {
fmt.Printf(" %d: %s\n", m.Line, m.Text)
}
fmt.Print("\n")
// if the sheet did not match the search, ignore it and move on
if sheet.Text == "" {
continue
}
}
// if colorization was requested, apply it here
if conf.Color(opts) {
sheet.Colorize(conf)
}
// output the cheatsheet title
fmt.Printf("%s:\n", sheet.Title)
// indent each line of content with two spaces
for _, line := range strings.Split(sheet.Text, "\n") {
fmt.Printf(" %s\n", line)
}
fmt.Println("")
}
}

View File

@ -5,8 +5,6 @@ import (
"os"
"strings"
"github.com/alecthomas/chroma/quick"
"github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/sheets"
)
@ -43,29 +41,11 @@ func cmdView(opts map[string]interface{}, conf config.Config) {
os.Exit(0)
}
if !conf.Color(opts) {
fmt.Print(sheet.Text)
os.Exit(0)
// apply colorization if requested
if conf.Color(opts) {
sheet.Colorize(conf)
}
// otherwise, colorize the output
// if the syntax was not specified, default to bash
lex := sheet.Syntax
if lex == "" {
lex = "bash"
}
// apply syntax highlighting
err = quick.Highlight(
os.Stdout,
sheet.Text,
lex,
conf.Formatter,
conf.Style,
)
// if colorization somehow failed, output non-colorized text
if err != nil {
fmt.Print(sheet.Text)
}
// display the cheatsheet
fmt.Print(sheet.Text)
}

View File

@ -2,18 +2,18 @@ Usage:
cheat [options] [<cheatsheet>]
Options:
--init Write a default config file to stdout
-c --colorize Colorize output
-d --directories List cheatsheet directories
-e --edit=<sheet> Edit <sheet>
-l --list List cheatsheets
-p --path=<name> Return only sheets found on path <name>
-r --regex Treat search <phrase> as a regex
-s --search=<phrase> Search cheatsheets for <phrase>
-t --tag=<tag> Return only sheets matching <tag>
-T --tags List all tags in use
-v --version Print the version number
--rm=<sheet> Remove (delete) <sheet>
--init Write a default config file to stdout
-c --colorize Colorize output
-d --directories List cheatsheet directories
-e --edit=<cheatsheet> Edit <cheatsheet>
-l --list List cheatsheets
-p --path=<name> Return only sheets found on path <name>
-r --regex Treat search <phrase> as a regex
-s --search=<phrase> Search cheatsheets for <phrase>
-t --tag=<tag> Return only sheets matching <tag>
-T --tags List all tags in use
-v --version Print the version number
--rm=<cheatsheet> Remove (delete) <cheatsheet>
Examples:

View File

@ -5,16 +5,19 @@ package main
import (
"fmt"
"os"
"path"
"runtime"
"strings"
"github.com/docopt/docopt-go"
"github.com/mitchellh/go-homedir"
"github.com/cheat/cheat/internal/cheatpath"
"github.com/cheat/cheat/internal/config"
"github.com/cheat/cheat/internal/installer"
)
const version = "3.5.0"
const version = "3.9.0"
func main() {
@ -32,6 +35,13 @@ func main() {
os.Exit(0)
}
// get the user's home directory
home, err := homedir.Dir()
if err != nil {
fmt.Fprintf(os.Stderr, "failed to get user home directory: %v\n", err)
os.Exit(1)
}
// read the envvars into a map of strings
envvars := map[string]string{}
for _, e := range os.Environ() {
@ -39,8 +49,8 @@ func main() {
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)
// identify the os-specifc paths at which configs may be located
confpaths, err := config.Paths(runtime.GOOS, home, envvars)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
os.Exit(1)
@ -49,22 +59,79 @@ func main() {
// search for the config file in the above paths
confpath, err := config.Path(confpaths)
if err != nil {
// prompt the user to create a config file
yes, err := installer.Prompt(
"A config file was not found. Would you like to create one now? [Y/n]",
true,
)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create config: %v\n", err)
os.Exit(1)
}
// exit early on a negative answer
if !yes {
os.Exit(0)
}
// read the config template
configs := configs()
// determine the appropriate paths for config data and (optional) community
// cheatsheets based on the user's platform
confpath = confpaths[0]
confdir := path.Dir(confpath)
// create paths for community and personal cheatsheets
community := path.Join(confdir, "/cheatsheets/community")
personal := path.Join(confdir, "/cheatsheets/personal")
// template the above paths into the default configs
configs = strings.Replace(configs, "COMMUNITY_PATH", community, -1)
configs = strings.Replace(configs, "PERSONAL_PATH", personal, -1)
// prompt the user to download the community cheatsheets
yes, err = installer.Prompt(
"Would you like to download the community cheatsheets? [Y/n]",
true,
)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to create config: %v\n", err)
os.Exit(1)
}
// clone the community cheatsheets if so instructed
if yes {
// clone the community cheatsheets
if err := installer.Clone(community); err != nil {
fmt.Fprintf(os.Stderr, "failed to create config: %v\n", err)
os.Exit(1)
}
// also create a directory for personal cheatsheets
if err := os.MkdirAll(personal, os.ModePerm); err != nil {
fmt.Fprintf(
os.Stderr,
"failed to create config: failed to create directory: %s: %v\n",
personal,
err)
os.Exit(1)
}
}
// the config file does not exist, so we'll try to create one
if err = config.Init(confpaths[0], configs()); err != nil {
if err = config.Init(confpath, configs); err != nil {
fmt.Fprintf(
os.Stderr,
"failed to create config file: %s: %v\n",
confpaths[0],
confpath,
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.")
fmt.Println("Please read this file for advanced configuration information.")
os.Exit(0)
}

View File

@ -41,33 +41,34 @@ cheatpaths:
# thus be overridden by more local cheatsheets. That being the case, you
# should probably list community cheatsheets first.
#
# Note that the paths and tags listed below are just examples. You may freely
# Note that the paths and tags listed below are placeholders. You may freely
# change them to suit your needs.
#
# TODO: regarding community cheatsheets: these must be installed separately.
# You may download them here:
# Community cheatsheets must be installed separately, though you may have
# downloaded them automatically when installing 'cheat'. If not, 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
path: ~/cheat/cheatsheets/community
path: COMMUNITY_PATH
tags: [ community ]
readonly: true
# If you have personalized cheatsheets, list them last. They will take
# precedence over the more global cheatsheets.
- name: personal
path: ~/cheat/cheatsheets/personal
path: PERSONAL_PATH
tags: [ personal ]
readonly: false
# While it requires no specific configuration here, it's also worth noting
# that 'cheat' will automatically append directories named '.cheat' within
# the current working directory to the 'cheatpath'. This can be very useful
# if you'd like to closely associate cheatsheets with, for example, a
# directory containing source code.
# While it requires no configuration here, it's also worth noting that
# 'cheat' will automatically append directories named '.cheat' within the
# current working directory to the 'cheatpath'. This can be very useful if
# you'd like to closely associate cheatsheets with, for example, a directory
# containing source code.
#
# Such "directory-scoped" cheatsheets will be treated as the most "local"
# cheatsheets, and will override less "local" cheatsheets. Likewise,

View File

@ -11,18 +11,18 @@ func usage() string {
cheat [options] [<cheatsheet>]
Options:
--init Write a default config file to stdout
-c --colorize Colorize output
-d --directories List cheatsheet directories
-e --edit=<sheet> Edit <sheet>
-l --list List cheatsheets
-p --path=<name> Return only sheets found on path <name>
-r --regex Treat search <phrase> as a regex
-s --search=<phrase> Search cheatsheets for <phrase>
-t --tag=<tag> Return only sheets matching <tag>
-T --tags List all tags in use
-v --version Print the version number
--rm=<sheet> Remove (delete) <sheet>
--init Write a default config file to stdout
-c --colorize Colorize output
-d --directories List cheatsheet directories
-e --edit=<cheatsheet> Edit <cheatsheet>
-l --list List cheatsheets
-p --path=<name> Return only sheets found on path <name>
-r --regex Treat search <phrase> as a regex
-s --search=<phrase> Search cheatsheets for <phrase>
-t --tag=<tag> Return only sheets matching <tag>
-T --tags List all tags in use
-v --version Print the version number
--rm=<cheatsheet> Remove (delete) <cheatsheet>
Examples:

View File

@ -32,33 +32,34 @@ cheatpaths:
# thus be overridden by more local cheatsheets. That being the case, you
# should probably list community cheatsheets first.
#
# Note that the paths and tags listed below are just examples. You may freely
# Note that the paths and tags listed below are placeholders. You may freely
# change them to suit your needs.
#
# TODO: regarding community cheatsheets: these must be installed separately.
# You may download them here:
# Community cheatsheets must be installed separately, though you may have
# downloaded them automatically when installing 'cheat'. If not, 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
path: ~/cheat/cheatsheets/community
path: COMMUNITY_PATH
tags: [ community ]
readonly: true
# If you have personalized cheatsheets, list them last. They will take
# precedence over the more global cheatsheets.
- name: personal
path: ~/cheat/cheatsheets/personal
path: PERSONAL_PATH
tags: [ personal ]
readonly: false
# While it requires no specific configuration here, it's also worth noting
# that 'cheat' will automatically append directories named '.cheat' within
# the current working directory to the 'cheatpath'. This can be very useful
# if you'd like to closely associate cheatsheets with, for example, a
# directory containing source code.
# While it requires no configuration here, it's also worth noting that
# 'cheat' will automatically append directories named '.cheat' within the
# current working directory to the 'cheatpath'. This can be very useful if
# you'd like to closely associate cheatsheets with, for example, a directory
# containing source code.
#
# Such "directory-scoped" cheatsheets will be treated as the most "local"
# cheatsheets, and will override less "local" cheatsheets. Likewise,

214
doc/cheat.1 Normal file
View File

@ -0,0 +1,214 @@
.\" Automatically generated by Pandoc 1.17.2
.\"
.TH "CHEAT" "1" "" "" "General Commands Manual"
.hy
.SH NAME
.PP
\f[B]cheat\f[] \[em] create and view command\-line cheatsheets
.SH SYNOPSIS
.PP
\f[B]cheat\f[] [options] [\f[I]CHEATSHEET\f[]]
.SH DESCRIPTION
.PP
\f[B]cheat\f[] allows you to create and view interactive cheatsheets on
the command\-line.
It was designed to help remind *nix system administrators of options for
commands that they use frequently, but not frequently enough to
remember.
.SH OPTIONS
.TP
.B \-\-init
Print a config file to stdout.
.RS
.RE
.TP
.B \-c, \-\-colorize
Colorize output.
.RS
.RE
.TP
.B \-d, \-\-directories
List cheatsheet directories.
.RS
.RE
.TP
.B \-e, \-\-edit=\f[I]CHEATSHEET\f[]
Open \f[I]CHEATSHEET\f[] for editing.
.RS
.RE
.TP
.B \-l, \-\-list
List available cheatsheets.
.RS
.RE
.TP
.B \-p, \-\-path=\f[I]PATH\f[]
Filter only to sheets found on path \f[I]PATH\f[].
.RS
.RE
.TP
.B \-r, \-\-regex
Treat search \f[I]PHRASE\f[] as a regular expression.
.RS
.RE
.TP
.B \-s, \-\-search=\f[I]PHRASE\f[]
Search cheatsheets for \f[I]PHRASE\f[].
.RS
.RE
.TP
.B \-t, \-\-tag=\f[I]TAG\f[]
Filter only to sheets tagged with \f[I]TAG\f[].
.RS
.RE
.TP
.B \-T, \-\-tags
List all tags in use.
.RS
.RE
.TP
.B \-v, \-\-version
Print the version number.
.RS
.RE
.TP
.B \-\-rm=\f[I]CHEATSHEET\f[]
Remove (deletes) \f[I]CHEATSHEET\f[].
.RS
.RE
.SH EXAMPLES
.TP
.B To view the foo cheatsheet:
cheat \f[I]foo\f[]
.RS
.RE
.TP
.B To edit (or create) the foo cheatsheet:
cheat \-e \f[I]foo\f[]
.RS
.RE
.TP
.B To edit (or create) the foo/bar cheatsheet on the \[aq]work\[aq] cheatpath:
cheat \-p \f[I]work\f[] \-e \f[I]foo/bar\f[]
.RS
.RE
.TP
.B To view all cheatsheet directories:
cheat \-d
.RS
.RE
.TP
.B To list all available cheatsheets:
cheat \-l
.RS
.RE
.TP
.B To list all cheatsheets whose titles match \[aq]apt\[aq]:
cheat \-l \f[I]apt\f[]
.RS
.RE
.TP
.B To list all tags in use:
cheat \-T
.RS
.RE
.TP
.B To list available cheatsheets that are tagged as \[aq]personal\[aq]:
cheat \-l \-t \f[I]personal\f[]
.RS
.RE
.TP
.B To search for \[aq]ssh\[aq] among all cheatsheets, and colorize matches:
cheat \-c \-s \f[I]ssh\f[]
.RS
.RE
.TP
.B To search (by regex) for cheatsheets that contain an IP address:
cheat \-c \-r \-s \f[I]\[aq](?:[0\-9]{1,3}.){3}[0\-9]{1,3}\[aq]\f[]
.RS
.RE
.TP
.B To remove (delete) the foo/bar cheatsheet:
cheat \-\-rm \f[I]foo/bar\f[]
.RS
.RE
.SH FILES
.SS Configuration
.PP
\f[B]cheat\f[] is configured via a YAML file that is conventionally
named \f[I]conf.yaml\f[].
\f[B]cheat\f[] will search for \f[I]conf.yaml\f[] in varying locations,
depending upon your platform:
.SS Linux, OSX, and other Unixes
.IP "1." 3
\f[B]CHEAT_CONFIG_PATH\f[]
.IP "2." 3
\f[B]XDG_CONFIG_HOME\f[]/cheat/conf.yaml
.IP "3." 3
\f[B]$HOME\f[]/.config/cheat/conf.yml
.IP "4." 3
\f[B]$HOME\f[]/.cheat/conf.yml
.SS Windows
.IP "1." 3
\f[B]CHEAT_CONFIG_PATH\f[]
.IP "2." 3
\f[B]APPDATA\f[]/cheat/conf.yml
.IP "3." 3
\f[B]PROGRAMDATA\f[]/cheat/conf.yml
.PP
\f[B]cheat\f[] will search in the order specified above.
The first \f[I]conf.yaml\f[] encountered will be respected.
.PP
If \f[B]cheat\f[] cannot locate a config file, it will ask if you\[aq]d
like to generate one automatically.
Alternatively, you may also generate a config file manually by running
\f[B]cheat \-\-init\f[] and saving its output to the appropriate
location for your platform.
.SS Cheatpaths
.PP
\f[B]cheat\f[] reads its cheatsheets from "cheatpaths", which are the
directories in which cheatsheets are stored.
Cheatpaths may be configured in \f[I]conf.yaml\f[], and viewed via
\f[B]cheat \-d\f[].
.PP
For detailed instructions on how to configure cheatpaths, please refer
to the comments in conf.yml.
.SS Autocompletion
.PP
Autocompletion scripts for \f[B]bash\f[], \f[B]zsh\f[], and
\f[B]fish\f[] are available for download:
.IP \[bu] 2
<https://github.com/cheat/cheat/blob/master/scripts/cheat.bash>
.IP \[bu] 2
<https://github.com/cheat/cheat/blob/master/scripts/cheat.fish>
.IP \[bu] 2
<https://github.com/cheat/cheat/blob/master/scripts/cheat.zsh>
.PP
The \f[B]bash\f[] and \f[B]zsh\f[] scripts provide optional integration
with \f[B]fzf\f[], if the latter is available on your \f[B]PATH\f[].
.PP
The installation process will vary per system and shell configuration,
and thus will not be discussed here.
.SH ENVIRONMENT
.TP
.B \f[B]CHEAT_CONFIG_PATH\f[]
The path at which the config file is available.
If \f[B]CHEAT_CONFIG_PATH\f[] is set, all other config paths will be
ignored.
.RS
.RE
.TP
.B \f[B]CHEAT_USE_FZF\f[]
If set, autocompletion scripts will attempt to integrate with
\f[B]fzf\f[].
.RS
.RE
.SH BUGS
.PP
See GitHub issues: <https://github.com/cheat/cheat/issues>
.SH AUTHOR
.PP
Christopher Allen Lane <chris@chris-allen-lane.com>
.SH SEE ALSO
.PP
\f[B]fzf(1)\f[]

183
doc/cheat.1.md Normal file
View File

@ -0,0 +1,183 @@
% CHEAT(1) | General Commands Manual
NAME
====
**cheat** — create and view command-line cheatsheets
SYNOPSIS
========
| **cheat** \[options] \[_CHEATSHEET_]
DESCRIPTION
===========
**cheat** allows you to create and view interactive cheatsheets on the
command-line. It was designed to help remind \*nix system administrators of
options for commands that they use frequently, but not frequently enough to
remember.
OPTIONS
=======
--init
: Print a config file to stdout.
-c, --colorize
: Colorize output.
-d, --directories
: List cheatsheet directories.
-e, --edit=_CHEATSHEET_
: Open _CHEATSHEET_ for editing.
-l, --list
: List available cheatsheets.
-p, --path=_PATH_
: Filter only to sheets found on path _PATH_.
-r, --regex
: Treat search _PHRASE_ as a regular expression.
-s, --search=_PHRASE_
: Search cheatsheets for _PHRASE_.
-t, --tag=_TAG_
: Filter only to sheets tagged with _TAG_.
-T, --tags
: List all tags in use.
-v, --version
: Print the version number.
--rm=_CHEATSHEET_
: Remove (deletes) _CHEATSHEET_.
EXAMPLES
========
To view the foo cheatsheet:
: cheat _foo_
To edit (or create) the foo cheatsheet:
: cheat -e _foo_
To edit (or create) the foo/bar cheatsheet on the 'work' cheatpath:
: cheat -p _work_ -e _foo/bar_
To view all cheatsheet directories:
: cheat -d
To list all available cheatsheets:
: cheat -l
To list all cheatsheets whose titles match 'apt':
: cheat -l _apt_
To list all tags in use:
: cheat -T
To list available cheatsheets that are tagged as 'personal':
: cheat -l -t _personal_
To search for 'ssh' among all cheatsheets, and colorize matches:
: cheat -c -s _ssh_
To search (by regex) for cheatsheets that contain an IP address:
: cheat -c -r -s _'(?:[0-9]{1,3}\.){3}[0-9]{1,3}'_
To remove (delete) the foo/bar cheatsheet:
: cheat --rm _foo/bar_
FILES
=====
Configuration
-------------
**cheat** is configured via a YAML file that is conventionally named
_conf.yaml_. **cheat** will search for _conf.yaml_ in varying locations,
depending upon your platform:
### Linux, OSX, and other Unixes ###
1. **CHEAT_CONFIG_PATH**
2. **XDG_CONFIG_HOME**/cheat/conf.yaml
3. **$HOME**/.config/cheat/conf.yml
4. **$HOME**/.cheat/conf.yml
### Windows ###
1. **CHEAT_CONFIG_PATH**
2. **APPDATA**/cheat/conf.yml
3. **PROGRAMDATA**/cheat/conf.yml
**cheat** will search in the order specified above. The first _conf.yaml_
encountered will be respected.
If **cheat** cannot locate a config file, it will ask if you'd like to generate
one automatically. Alternatively, you may also generate a config file manually
by running **cheat --init** and saving its output to the appropriate location
for your platform.
Cheatpaths
----------
**cheat** reads its cheatsheets from "cheatpaths", which are the directories in
which cheatsheets are stored. Cheatpaths may be configured in _conf.yaml_, and
viewed via **cheat -d**.
For detailed instructions on how to configure cheatpaths, please refer to the
comments in conf.yml.
Autocompletion
--------------
Autocompletion scripts for **bash**, **zsh**, and **fish** are available for
download:
- <https://github.com/cheat/cheat/blob/master/scripts/cheat.bash>
- <https://github.com/cheat/cheat/blob/master/scripts/cheat.fish>
- <https://github.com/cheat/cheat/blob/master/scripts/cheat.zsh>
The **bash** and **zsh** scripts provide optional integration with **fzf**, if
the latter is available on your **PATH**.
The installation process will vary per system and shell configuration, and thus
will not be discussed here.
ENVIRONMENT
===========
**CHEAT_CONFIG_PATH**
: The path at which the config file is available. If **CHEAT_CONFIG_PATH** is
set, all other config paths will be ignored.
**CHEAT_USE_FZF**
: If set, autocompletion scripts will attempt to integrate with **fzf**.
BUGS
====
See GitHub issues: <https://github.com/cheat/cheat/issues>
AUTHOR
======
Christopher Allen Lane <chris@chris-allen-lane.com>
SEE ALSO
========
**fzf(1)**

8
go.mod
View File

@ -1,14 +1,18 @@
module github.com/cheat/cheat
go 1.13
go 1.14
require (
github.com/alecthomas/chroma v0.7.1
github.com/davecgh/go-spew v1.1.1
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-isatty v0.0.12
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
github.com/mitchellh/go-homedir v1.1.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/sergi/go-diff v1.1.0 // indirect
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0
gopkg.in/yaml.v2 v2.2.8
)

24
go.sum
View File

@ -7,6 +7,7 @@ github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBo
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -16,33 +17,52 @@ github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -9,7 +9,11 @@ import (
// Paths returns config file paths that are appropriate for the operating
// system
func Paths(sys string, envvars map[string]string) ([]string, error) {
func Paths(
sys string,
home 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 {
@ -32,10 +36,10 @@ func Paths(sys string, envvars map[string]string) ([]string, error) {
paths = append(paths, path.Join(xdgpath, "/cheat/conf.yml"))
}
// `HOME` will always be set on a POSIX-compliant system, though
// if `XDG_CONFIG_HOME` is not set, search the user's home directory
paths = append(paths, []string{
path.Join(envvars["HOME"], ".config/cheat/conf.yml"),
path.Join(envvars["HOME"], ".cheat/conf.yml"),
path.Join(home, ".config/cheat/conf.yml"),
path.Join(home, ".cheat/conf.yml"),
}...)
return paths, nil

View File

@ -11,9 +11,11 @@ import (
// *nix platforms
func TestValidatePathsNix(t *testing.T) {
// mock the user's home directory
home := "/home/foo"
// mock some envvars
envvars := map[string]string{
"HOME": "/home/foo",
"XDG_CONFIG_HOME": "/home/bar",
}
@ -27,7 +29,7 @@ func TestValidatePathsNix(t *testing.T) {
// test each *nix os
for _, os := range oses {
// get the paths for the platform
paths, err := Paths(os, envvars)
paths, err := Paths(os, home, envvars)
if err != nil {
t.Errorf("paths returned an error: %v", err)
}
@ -54,10 +56,11 @@ func TestValidatePathsNix(t *testing.T) {
// on *nix platforms when `XDG_CONFIG_HOME is not set
func TestValidatePathsNixNoXDG(t *testing.T) {
// mock the user's home directory
home := "/home/foo"
// mock some envvars
envvars := map[string]string{
"HOME": "/home/foo",
}
envvars := map[string]string{}
// specify the platforms to test
oses := []string{
@ -69,7 +72,7 @@ func TestValidatePathsNixNoXDG(t *testing.T) {
// test each *nix os
for _, os := range oses {
// get the paths for the platform
paths, err := Paths(os, envvars)
paths, err := Paths(os, home, envvars)
if err != nil {
t.Errorf("paths returned an error: %v", err)
}
@ -95,6 +98,9 @@ func TestValidatePathsNixNoXDG(t *testing.T) {
// on Windows platforms
func TestValidatePathsWindows(t *testing.T) {
// mock the user's home directory
home := "not-used-on-windows"
// mock some envvars
envvars := map[string]string{
"APPDATA": "/apps",
@ -102,7 +108,7 @@ func TestValidatePathsWindows(t *testing.T) {
}
// get the paths for the platform
paths, err := Paths("windows", envvars)
paths, err := Paths("windows", home, envvars)
if err != nil {
t.Errorf("paths returned an error: %v", err)
}
@ -126,7 +132,7 @@ func TestValidatePathsWindows(t *testing.T) {
// TestValidatePathsUnsupported asserts that an error is returned on
// unsupported platforms
func TestValidatePathsUnsupported(t *testing.T) {
_, err := Paths("unsupported", map[string]string{})
_, err := Paths("unsupported", "", map[string]string{})
if err == nil {
t.Errorf("failed to return error on unsupported platform")
}
@ -136,15 +142,17 @@ func TestValidatePathsUnsupported(t *testing.T) {
// returned when `CHEAT_CONFIG_PATH` is explicitly specified.
func TestValidatePathsCheatConfigPath(t *testing.T) {
// mock the user's home directory
home := "/home/foo"
// 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)
paths, err := Paths("linux", home, envvars)
if err != nil {
t.Errorf("paths returned an error: %v", err)
}

View File

@ -1,6 +1,7 @@
package frontmatter
import (
"fmt"
"strings"
"gopkg.in/yaml.v1"
@ -28,7 +29,16 @@ func Parse(markdown string) (string, Frontmatter, error) {
// 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
// return an error if the frontmatter parses into the wrong number of parts
if len(parts) != 3 {
return markdown, fm, fmt.Errorf("failed to delimit frontmatter")
}
// return an error if the YAML cannot be unmarshalled
if err := yaml.Unmarshal([]byte(parts[1]), &fm); err != nil {
return markdown, fm, fmt.Errorf("failed to unmarshal frontmatter: %v", err)
}
return strings.TrimSpace(parts[2]), fm, nil
}

View File

@ -69,3 +69,27 @@ func TestHasNoFrontmatter(t *testing.T) {
t.Errorf("failed to parse tags: want: len 0, got: len %d", len(fm.Tags))
}
}
// TestHasInvalidFrontmatter asserts that markdown is properly parsed when it
// contains invalid frontmatter
func TestHasInvalidFrontmatter(t *testing.T) {
// stub our cheatsheet content (with invalid frontmatter)
markdown := `---
syntax: go
tags: [ test ]
To foo the bar: baz`
// parse the frontmatter
text, _, err := Parse(markdown)
// assert that an error was returned
if err == nil {
t.Error("failed to error on invalid frontmatter")
}
// assert that the "raw" markdown was returned
if text != markdown {
t.Errorf("failed to parse text: want: %s, got: %s", markdown, text)
}
}

View File

@ -0,0 +1,24 @@
package installer
import (
"fmt"
"os"
"os/exec"
)
const cloneURL = "https://github.com/cheat/cheatsheets.git"
// Clone clones the community cheatsheets
func Clone(path string) error {
// perform the clone in a shell
cmd := exec.Command("git", "clone", cloneURL, path)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return fmt.Errorf("failed to clone cheatsheets: %v", err)
}
return nil
}

View File

@ -0,0 +1,37 @@
package installer
import (
"bufio"
"fmt"
"os"
"strings"
)
// Prompt prompts the user for a answer
func Prompt(prompt string, def bool) (bool, error) {
// initialize a line reader
reader := bufio.NewReader(os.Stdin)
// display the prompt
fmt.Print(fmt.Sprintf("%s: ", prompt))
// read the answer
ans, err := reader.ReadString('\n')
if err != nil {
return false, fmt.Errorf("failed to parse input: %v", err)
}
// normalize the answer
ans = strings.ToLower(strings.TrimRight(ans, "\n"))
// return the appropriate response
switch ans {
case "y":
return true, nil
case "":
return def, nil
default:
return false, nil
}
}

View File

@ -0,0 +1,37 @@
package sheet
import (
"bytes"
"github.com/cheat/cheat/internal/config"
"github.com/alecthomas/chroma/quick"
)
// Colorize applies syntax-highlighting to a cheatsheet's Text.
func (s *Sheet) Colorize(conf config.Config) {
// if the syntax was not specified, default to bash
lex := s.Syntax
if lex == "" {
lex = "bash"
}
// write colorized text into a buffer
var buf bytes.Buffer
err := quick.Highlight(
&buf,
s.Text,
lex,
conf.Formatter,
conf.Style,
)
// if colorization somehow failed, do nothing
if err != nil {
return
}
// otherwise, swap the cheatsheet's Text with its colorized equivalent
s.Text = buf.String()
}

View File

@ -1,7 +0,0 @@
package sheet
// Match encapsulates search matches within cheatsheets
type Match struct {
Line int
Text string
}

View File

@ -3,43 +3,22 @@ package sheet
import (
"regexp"
"strings"
"github.com/mgutz/ansi"
)
// Search searches for regexp matches in a cheatsheet's text, and optionally
// colorizes matching strings.
func (s *Sheet) Search(reg *regexp.Regexp, colorize bool) []Match {
// Search returns lines within a sheet's Text that match the search regex
func (s *Sheet) Search(reg *regexp.Regexp) string {
// record matches
matches := []Match{}
matches := ""
// search through the cheatsheet's text line by line
// TODO: searching line-by-line is surely the "naive" approach. Revisit this
// later with an eye for performance improvements.
for linenum, line := range strings.Split(s.Text, "\n") {
for _, line := range strings.Split(s.Text, "\n\n") {
// exit early if the line doesn't match the regex
if !reg.MatchString(line) {
continue
if reg.MatchString(line) {
matches += line + "\n\n"
}
// init the match
m := Match{
Line: linenum + 1,
Text: strings.TrimSpace(line),
}
// colorize the matching text if so configured
if colorize {
m.Text = reg.ReplaceAllStringFunc(m.Text, func(matched string) string {
return ansi.Color(matched, "red+b")
})
}
// record the match
matches = append(matches, m)
}
return matches
return strings.TrimSpace(matches)
}

View File

@ -4,8 +4,6 @@ import (
"reflect"
"regexp"
"testing"
"github.com/davecgh/go-spew/spew"
)
// TestSearchNoMatch ensures that the expected output is returned when no
@ -24,21 +22,21 @@ func TestSearchNoMatch(t *testing.T) {
}
// search the sheet
matches := sheet.Search(reg, false)
matches := sheet.Search(reg)
// assert that no matches were found
if len(matches) != 0 {
t.Errorf("failure: expected no matches: got: %s", spew.Sdump(matches))
if matches != "" {
t.Errorf("failure: expected no matches: got: %s", matches)
}
}
// TestSearchSingleMatchNoColor asserts that the expected output is returned
// when a single match is returned, and no colorization is applied.
func TestSearchSingleMatchNoColor(t *testing.T) {
// TestSearchSingleMatch asserts that the expected output is returned
// when a single match is returned
func TestSearchSingleMatch(t *testing.T) {
// mock a cheatsheet
sheet := Sheet{
Text: "The quick brown fox\njumped over\nthe lazy dog.",
Text: "The quick brown fox\njumped over\n\nthe lazy dog.",
}
// compile the search regex
@ -48,69 +46,28 @@ func TestSearchSingleMatchNoColor(t *testing.T) {
}
// search the sheet
matches := sheet.Search(reg, false)
matches := sheet.Search(reg)
// specify the expected results
want := []Match{
Match{
Line: 1,
Text: "The quick brown fox",
},
}
want := "The quick brown fox\njumped over"
// assert that the correct matches were returned
if !reflect.DeepEqual(matches, want) {
if matches != want {
t.Errorf(
"failed to return expected matches: want:\n%s, got:\n%s",
spew.Sdump(want),
spew.Sdump(matches),
want,
matches,
)
}
}
// TestSearchSingleMatchColorized asserts that the expected output is returned
// when a single match is returned, and colorization is applied
func TestSearchSingleMatchColorized(t *testing.T) {
// TestSearchMultiMatch asserts that the expected output is returned
// when a multiple matches are returned
func TestSearchMultiMatch(t *testing.T) {
// mock a cheatsheet
sheet := Sheet{
Text: "The quick brown fox\njumped over\nthe lazy dog.",
}
// compile the search regex
reg, err := regexp.Compile("(?i)fox")
if err != nil {
t.Errorf("failed to compile regex: %v", err)
}
// search the sheet
matches := sheet.Search(reg, true)
// specify the expected results
want := []Match{
Match{
Line: 1,
Text: "The quick brown \x1b[1;31mfox\x1b[0m",
},
}
// assert that the correct matches were returned
if !reflect.DeepEqual(matches, want) {
t.Errorf(
"failed to return expected matches: want:\n%s, got:\n%s",
spew.Sdump(want),
spew.Sdump(matches),
)
}
}
// TestSearchMultiMatchNoColor asserts that the expected output is returned
// when a multiple matches are returned, and no colorization is applied
func TestSearchMultiMatchNoColor(t *testing.T) {
// mock a cheatsheet
sheet := Sheet{
Text: "The quick brown fox\njumped over\nthe lazy dog.",
Text: "The quick brown fox\n\njumped over\n\nthe lazy dog.",
}
// compile the search regex
@ -120,66 +77,17 @@ func TestSearchMultiMatchNoColor(t *testing.T) {
}
// search the sheet
matches := sheet.Search(reg, false)
matches := sheet.Search(reg)
// specify the expected results
want := []Match{
Match{
Line: 1,
Text: "The quick brown fox",
},
Match{
Line: 3,
Text: "the lazy dog.",
},
}
want := "The quick brown fox\n\nthe lazy dog."
// assert that the correct matches were returned
if !reflect.DeepEqual(matches, want) {
t.Errorf(
"failed to return expected matches: want:\n%s, got:\n%s",
spew.Sdump(want),
spew.Sdump(matches),
)
}
}
// TestSearchMultiMatchColorized asserts that the expected output is returned
// when a multiple matches are returned, and colorization is applied
func TestSearchMultiMatchColorized(t *testing.T) {
// mock a cheatsheet
sheet := Sheet{
Text: "The quick brown fox\njumped over\nthe lazy dog.",
}
// compile the search regex
reg, err := regexp.Compile("(?i)the")
if err != nil {
t.Errorf("failed to compile regex: %v", err)
}
// search the sheet
matches := sheet.Search(reg, true)
// specify the expected results
want := []Match{
Match{
Line: 1,
Text: "\x1b[1;31mThe\x1b[0m quick brown fox",
},
Match{
Line: 3,
Text: "\x1b[1;31mthe\x1b[0m lazy dog.",
},
}
// assert that the correct matches were returned
if !reflect.DeepEqual(matches, want) {
t.Errorf(
"failed to return expected matches: want:\n%s, got:\n%s",
spew.Sdump(want),
spew.Sdump(matches),
want,
matches,
)
}
}

View File

@ -33,7 +33,7 @@ func Load(cheatpaths []cp.Cheatpath) ([]map[string]sheet.Sheet, error) {
// fail if an error occurred while walking the directory
if err != nil {
return fmt.Errorf("error walking path: %v", err)
return fmt.Errorf("failed to walk path: %v", err)
}
// don't register directories as cheatsheets
@ -61,7 +61,12 @@ func Load(cheatpaths []cp.Cheatpath) ([]map[string]sheet.Sheet, error) {
// parse the cheatsheet file into a `sheet` struct
s, err := sheet.New(title, path, cheatpath.Tags, cheatpath.ReadOnly)
if err != nil {
return fmt.Errorf("could not create sheet: %v", err)
return fmt.Errorf(
"failed to load sheet: %s, path: %s, err: %v",
title,
path,
err,
)
}
// register the cheatsheet on its cheatpath, keyed by its title

57
scripts/cheat.zsh Executable file
View File

@ -0,0 +1,57 @@
#compdef cheat
local cheats taglist pathlist
_cheat_complete_cheatsheets()
{
cheats=("${(f)$(cheat -l -t personal | tail -n +2 | cut -d' ' -f1)}")
_describe -t cheats 'cheats' cheats
}
_cheat_complete_tags()
{
taglist=("${(f)$(cheat -T)}")
_describe -t taglist 'taglist' taglist
}
_cheat_complete_paths()
{
pathlist=("${(f)$(cheat -d | cut -d':' -f1)}")
_describe -t pathlist 'pathlist' pathlist
}
_cheat() {
_arguments -C \
'(--init)--init[Write a default config file to stdout]: :->none' \
'(-c --colorize)'{-c,--colorize}'[Colorize output]: :->none' \
'(-d --directories)'{-d,--directories}'[List cheatsheet directories]: :->none' \
'(-e --edit)'{-e,--edit}'[Edit <sheet>]: :->full' \
'(-l --list)'{-l,--list}'[List cheatsheets]: :->full' \
'(-p --path)'{-p,--path}'[Return only sheets found on path <name>]: :->pathlist' \
'(-r --regex)'{-r,--regex}'[Treat search <phrase> as a regex]: :->none' \
'(-s --search)'{-s,--search}'[Search cheatsheets for <phrase>]: :->none' \
'(-t --tag)'{-t,--tag}'[Return only sheets matching <tag>]: :->taglist' \
'(-T --tags)'{-T,--tags}'[List all tags in use]: :->none' \
'(-v --version)'{-v,--version}'[Print the version number]: :->none' \
'(--rm)--rm[Remove (delete) <sheet>]: :->full' \
case $state in
(none)
;;
(full)
_cheat_complete_cheatsheets
;;
(taglist)
_cheat_complete_tags
;;
(pathlist)
_cheat_complete_paths
;;
(*)
_cheat_complete_cheatsheets
;;
esac
}
_cheat

View File

@ -1,9 +0,0 @@
language: go
go:
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 Yasuhiro Matsumoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,48 +0,0 @@
# go-colorable
[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable)
[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable)
[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master)
[![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable)
Colorable writer for windows.
For example, most of logger packages doesn't show colors on windows. (I know we can do it with ansicon. But I don't want.)
This package is possible to handle escape sequence for ansi color on windows.
## Too Bad!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/bad.png)
## So Good!
![](https://raw.githubusercontent.com/mattn/go-colorable/gh-pages/good.png)
## Usage
```go
logrus.SetFormatter(&logrus.TextFormatter{ForceColors: true})
logrus.SetOutput(colorable.NewColorableStdout())
logrus.Info("succeeded")
logrus.Warn("not correct")
logrus.Error("something error")
logrus.Fatal("panic")
```
You can compile above code on non-windows OSs.
## Installation
```
$ go get github.com/mattn/go-colorable
```
# License
MIT
# Author
Yasuhiro Matsumoto (a.k.a mattn)

View File

@ -1,29 +0,0 @@
// +build appengine
package colorable
import (
"io"
"os"
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
}
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

View File

@ -1,30 +0,0 @@
// +build !windows
// +build !appengine
package colorable
import (
"io"
"os"
_ "github.com/mattn/go-isatty"
)
// NewColorable return new instance of Writer which handle escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
}
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}

View File

@ -1,884 +0,0 @@
// +build windows
// +build !appengine
package colorable
import (
"bytes"
"io"
"math"
"os"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/mattn/go-isatty"
)
const (
foregroundBlue = 0x1
foregroundGreen = 0x2
foregroundRed = 0x4
foregroundIntensity = 0x8
foregroundMask = (foregroundRed | foregroundBlue | foregroundGreen | foregroundIntensity)
backgroundBlue = 0x10
backgroundGreen = 0x20
backgroundRed = 0x40
backgroundIntensity = 0x80
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
)
type wchar uint16
type short int16
type dword uint32
type word uint16
type coord struct {
x short
y short
}
type smallRect struct {
left short
top short
right short
bottom short
}
type consoleScreenBufferInfo struct {
size coord
cursorPosition coord
attributes word
window smallRect
maximumWindowSize coord
}
type consoleCursorInfo struct {
size dword
visible int32
}
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo")
procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute")
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
procFillConsoleOutputAttribute = kernel32.NewProc("FillConsoleOutputAttribute")
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
)
// Writer provide colorable Writer to the console
type Writer struct {
out io.Writer
handle syscall.Handle
oldattr word
oldpos coord
}
// NewColorable return new instance of Writer which handle escape sequence from File.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
}
if isatty.IsTerminal(file.Fd()) {
var csbi consoleScreenBufferInfo
handle := syscall.Handle(file.Fd())
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
return &Writer{out: file, handle: handle, oldattr: csbi.attributes, oldpos: coord{0, 0}}
}
return file
}
// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return NewColorable(os.Stdout)
}
// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return NewColorable(os.Stderr)
}
var color256 = map[int]int{
0: 0x000000,
1: 0x800000,
2: 0x008000,
3: 0x808000,
4: 0x000080,
5: 0x800080,
6: 0x008080,
7: 0xc0c0c0,
8: 0x808080,
9: 0xff0000,
10: 0x00ff00,
11: 0xffff00,
12: 0x0000ff,
13: 0xff00ff,
14: 0x00ffff,
15: 0xffffff,
16: 0x000000,
17: 0x00005f,
18: 0x000087,
19: 0x0000af,
20: 0x0000d7,
21: 0x0000ff,
22: 0x005f00,
23: 0x005f5f,
24: 0x005f87,
25: 0x005faf,
26: 0x005fd7,
27: 0x005fff,
28: 0x008700,
29: 0x00875f,
30: 0x008787,
31: 0x0087af,
32: 0x0087d7,
33: 0x0087ff,
34: 0x00af00,
35: 0x00af5f,
36: 0x00af87,
37: 0x00afaf,
38: 0x00afd7,
39: 0x00afff,
40: 0x00d700,
41: 0x00d75f,
42: 0x00d787,
43: 0x00d7af,
44: 0x00d7d7,
45: 0x00d7ff,
46: 0x00ff00,
47: 0x00ff5f,
48: 0x00ff87,
49: 0x00ffaf,
50: 0x00ffd7,
51: 0x00ffff,
52: 0x5f0000,
53: 0x5f005f,
54: 0x5f0087,
55: 0x5f00af,
56: 0x5f00d7,
57: 0x5f00ff,
58: 0x5f5f00,
59: 0x5f5f5f,
60: 0x5f5f87,
61: 0x5f5faf,
62: 0x5f5fd7,
63: 0x5f5fff,
64: 0x5f8700,
65: 0x5f875f,
66: 0x5f8787,
67: 0x5f87af,
68: 0x5f87d7,
69: 0x5f87ff,
70: 0x5faf00,
71: 0x5faf5f,
72: 0x5faf87,
73: 0x5fafaf,
74: 0x5fafd7,
75: 0x5fafff,
76: 0x5fd700,
77: 0x5fd75f,
78: 0x5fd787,
79: 0x5fd7af,
80: 0x5fd7d7,
81: 0x5fd7ff,
82: 0x5fff00,
83: 0x5fff5f,
84: 0x5fff87,
85: 0x5fffaf,
86: 0x5fffd7,
87: 0x5fffff,
88: 0x870000,
89: 0x87005f,
90: 0x870087,
91: 0x8700af,
92: 0x8700d7,
93: 0x8700ff,
94: 0x875f00,
95: 0x875f5f,
96: 0x875f87,
97: 0x875faf,
98: 0x875fd7,
99: 0x875fff,
100: 0x878700,
101: 0x87875f,
102: 0x878787,
103: 0x8787af,
104: 0x8787d7,
105: 0x8787ff,
106: 0x87af00,
107: 0x87af5f,
108: 0x87af87,
109: 0x87afaf,
110: 0x87afd7,
111: 0x87afff,
112: 0x87d700,
113: 0x87d75f,
114: 0x87d787,
115: 0x87d7af,
116: 0x87d7d7,
117: 0x87d7ff,
118: 0x87ff00,
119: 0x87ff5f,
120: 0x87ff87,
121: 0x87ffaf,
122: 0x87ffd7,
123: 0x87ffff,
124: 0xaf0000,
125: 0xaf005f,
126: 0xaf0087,
127: 0xaf00af,
128: 0xaf00d7,
129: 0xaf00ff,
130: 0xaf5f00,
131: 0xaf5f5f,
132: 0xaf5f87,
133: 0xaf5faf,
134: 0xaf5fd7,
135: 0xaf5fff,
136: 0xaf8700,
137: 0xaf875f,
138: 0xaf8787,
139: 0xaf87af,
140: 0xaf87d7,
141: 0xaf87ff,
142: 0xafaf00,
143: 0xafaf5f,
144: 0xafaf87,
145: 0xafafaf,
146: 0xafafd7,
147: 0xafafff,
148: 0xafd700,
149: 0xafd75f,
150: 0xafd787,
151: 0xafd7af,
152: 0xafd7d7,
153: 0xafd7ff,
154: 0xafff00,
155: 0xafff5f,
156: 0xafff87,
157: 0xafffaf,
158: 0xafffd7,
159: 0xafffff,
160: 0xd70000,
161: 0xd7005f,
162: 0xd70087,
163: 0xd700af,
164: 0xd700d7,
165: 0xd700ff,
166: 0xd75f00,
167: 0xd75f5f,
168: 0xd75f87,
169: 0xd75faf,
170: 0xd75fd7,
171: 0xd75fff,
172: 0xd78700,
173: 0xd7875f,
174: 0xd78787,
175: 0xd787af,
176: 0xd787d7,
177: 0xd787ff,
178: 0xd7af00,
179: 0xd7af5f,
180: 0xd7af87,
181: 0xd7afaf,
182: 0xd7afd7,
183: 0xd7afff,
184: 0xd7d700,
185: 0xd7d75f,
186: 0xd7d787,
187: 0xd7d7af,
188: 0xd7d7d7,
189: 0xd7d7ff,
190: 0xd7ff00,
191: 0xd7ff5f,
192: 0xd7ff87,
193: 0xd7ffaf,
194: 0xd7ffd7,
195: 0xd7ffff,
196: 0xff0000,
197: 0xff005f,
198: 0xff0087,
199: 0xff00af,
200: 0xff00d7,
201: 0xff00ff,
202: 0xff5f00,
203: 0xff5f5f,
204: 0xff5f87,
205: 0xff5faf,
206: 0xff5fd7,
207: 0xff5fff,
208: 0xff8700,
209: 0xff875f,
210: 0xff8787,
211: 0xff87af,
212: 0xff87d7,
213: 0xff87ff,
214: 0xffaf00,
215: 0xffaf5f,
216: 0xffaf87,
217: 0xffafaf,
218: 0xffafd7,
219: 0xffafff,
220: 0xffd700,
221: 0xffd75f,
222: 0xffd787,
223: 0xffd7af,
224: 0xffd7d7,
225: 0xffd7ff,
226: 0xffff00,
227: 0xffff5f,
228: 0xffff87,
229: 0xffffaf,
230: 0xffffd7,
231: 0xffffff,
232: 0x080808,
233: 0x121212,
234: 0x1c1c1c,
235: 0x262626,
236: 0x303030,
237: 0x3a3a3a,
238: 0x444444,
239: 0x4e4e4e,
240: 0x585858,
241: 0x626262,
242: 0x6c6c6c,
243: 0x767676,
244: 0x808080,
245: 0x8a8a8a,
246: 0x949494,
247: 0x9e9e9e,
248: 0xa8a8a8,
249: 0xb2b2b2,
250: 0xbcbcbc,
251: 0xc6c6c6,
252: 0xd0d0d0,
253: 0xdadada,
254: 0xe4e4e4,
255: 0xeeeeee,
}
// `\033]0;TITLESTR\007`
func doTitleSequence(er *bytes.Reader) error {
var c byte
var err error
c, err = er.ReadByte()
if err != nil {
return err
}
if c != '0' && c != '2' {
return nil
}
c, err = er.ReadByte()
if err != nil {
return err
}
if c != ';' {
return nil
}
title := make([]byte, 0, 80)
for {
c, err = er.ReadByte()
if err != nil {
return err
}
if c == 0x07 || c == '\n' {
break
}
title = append(title, c)
}
if len(title) > 0 {
title8, err := syscall.UTF16PtrFromString(string(title))
if err == nil {
procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8)))
}
}
return nil
}
// Write write data on console
func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
er := bytes.NewReader(data)
var bw [1]byte
loop:
for {
c1, err := er.ReadByte()
if err != nil {
break loop
}
if c1 != 0x1b {
bw[0] = c1
w.out.Write(bw[:])
continue
}
c2, err := er.ReadByte()
if err != nil {
break loop
}
if c2 == ']' {
if err := doTitleSequence(er); err != nil {
break loop
}
continue
}
if c2 != 0x5b {
continue
}
var buf bytes.Buffer
var m byte
for {
c, err := er.ReadByte()
if err != nil {
break loop
}
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
m = c
break
}
buf.Write([]byte(string(c)))
}
switch m {
case 'A':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'B':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'C':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'D':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'E':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0
csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'F':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0
csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'G':
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = short(n - 1)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'H', 'f':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
if buf.Len() > 0 {
token := strings.Split(buf.String(), ";")
switch len(token) {
case 1:
n1, err := strconv.Atoi(token[0])
if err != nil {
continue
}
csbi.cursorPosition.y = short(n1 - 1)
case 2:
n1, err := strconv.Atoi(token[0])
if err != nil {
continue
}
n2, err := strconv.Atoi(token[1])
if err != nil {
continue
}
csbi.cursorPosition.x = short(n2 - 1)
csbi.cursorPosition.y = short(n1 - 1)
}
} else {
csbi.cursorPosition.y = 0
}
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'J':
n := 0
if buf.Len() > 0 {
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
}
var count, written dword
var cursor coord
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
switch n {
case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x)
case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x)
}
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'K':
n := 0
if buf.Len() > 0 {
n, err = strconv.Atoi(buf.String())
if err != nil {
continue
}
}
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
var cursor coord
var count, written dword
switch n {
case 0:
cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x - 1)
case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x)
case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y}
count = dword(csbi.size.x)
}
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
attr := csbi.attributes
cs := buf.String()
if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr))
continue
}
token := strings.Split(cs, ";")
for i := 0; i < len(token); i++ {
ns := token[i]
if n, err = strconv.Atoi(ns); err == nil {
switch {
case n == 0 || n == 100:
attr = w.oldattr
case 1 <= n && n <= 5:
attr |= foregroundIntensity
case n == 7:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
case n == 22 || n == 25:
attr |= foregroundIntensity
case n == 27:
attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4)
case 30 <= n && n <= 37:
attr &= backgroundMask
if (n-30)&1 != 0 {
attr |= foregroundRed
}
if (n-30)&2 != 0 {
attr |= foregroundGreen
}
if (n-30)&4 != 0 {
attr |= foregroundBlue
}
case n == 38: // set foreground color.
if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") {
if n256, err := strconv.Atoi(token[i+2]); err == nil {
if n256foreAttr == nil {
n256setup()
}
attr &= backgroundMask
attr |= n256foreAttr[n256]
i += 2
}
} else {
attr = attr & (w.oldattr & backgroundMask)
}
case n == 39: // reset foreground color.
attr &= backgroundMask
attr |= w.oldattr & foregroundMask
case 40 <= n && n <= 47:
attr &= foregroundMask
if (n-40)&1 != 0 {
attr |= backgroundRed
}
if (n-40)&2 != 0 {
attr |= backgroundGreen
}
if (n-40)&4 != 0 {
attr |= backgroundBlue
}
case n == 48: // set background color.
if i < len(token)-2 && token[i+1] == "5" {
if n256, err := strconv.Atoi(token[i+2]); err == nil {
if n256backAttr == nil {
n256setup()
}
attr &= foregroundMask
attr |= n256backAttr[n256]
i += 2
}
} else {
attr = attr & (w.oldattr & foregroundMask)
}
case n == 49: // reset foreground color.
attr &= foregroundMask
attr |= w.oldattr & backgroundMask
case 90 <= n && n <= 97:
attr = (attr & backgroundMask)
attr |= foregroundIntensity
if (n-90)&1 != 0 {
attr |= foregroundRed
}
if (n-90)&2 != 0 {
attr |= foregroundGreen
}
if (n-90)&4 != 0 {
attr |= foregroundBlue
}
case 100 <= n && n <= 107:
attr = (attr & foregroundMask)
attr |= backgroundIntensity
if (n-100)&1 != 0 {
attr |= backgroundRed
}
if (n-100)&2 != 0 {
attr |= backgroundGreen
}
if (n-100)&4 != 0 {
attr |= backgroundBlue
}
}
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr))
}
}
case 'h':
var ci consoleCursorInfo
cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
}
case 'l':
var ci consoleCursorInfo
cs := buf.String()
if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci)))
}
case 's':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition
case 'u':
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
}
}
return len(data), nil
}
type consoleColor struct {
rgb int
red bool
green bool
blue bool
intensity bool
}
func (c consoleColor) foregroundAttr() (attr word) {
if c.red {
attr |= foregroundRed
}
if c.green {
attr |= foregroundGreen
}
if c.blue {
attr |= foregroundBlue
}
if c.intensity {
attr |= foregroundIntensity
}
return
}
func (c consoleColor) backgroundAttr() (attr word) {
if c.red {
attr |= backgroundRed
}
if c.green {
attr |= backgroundGreen
}
if c.blue {
attr |= backgroundBlue
}
if c.intensity {
attr |= backgroundIntensity
}
return
}
var color16 = []consoleColor{
{0x000000, false, false, false, false},
{0x000080, false, false, true, false},
{0x008000, false, true, false, false},
{0x008080, false, true, true, false},
{0x800000, true, false, false, false},
{0x800080, true, false, true, false},
{0x808000, true, true, false, false},
{0xc0c0c0, true, true, true, false},
{0x808080, false, false, false, true},
{0x0000ff, false, false, true, true},
{0x00ff00, false, true, false, true},
{0x00ffff, false, true, true, true},
{0xff0000, true, false, false, true},
{0xff00ff, true, false, true, true},
{0xffff00, true, true, false, true},
{0xffffff, true, true, true, true},
}
type hsv struct {
h, s, v float32
}
func (a hsv) dist(b hsv) float32 {
dh := a.h - b.h
switch {
case dh > 0.5:
dh = 1 - dh
case dh < -0.5:
dh = -1 - dh
}
ds := a.s - b.s
dv := a.v - b.v
return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv)))
}
func toHSV(rgb int) hsv {
r, g, b := float32((rgb&0xFF0000)>>16)/256.0,
float32((rgb&0x00FF00)>>8)/256.0,
float32(rgb&0x0000FF)/256.0
min, max := minmax3f(r, g, b)
h := max - min
if h > 0 {
if max == r {
h = (g - b) / h
if h < 0 {
h += 6
}
} else if max == g {
h = 2 + (b-r)/h
} else {
h = 4 + (r-g)/h
}
}
h /= 6.0
s := max - min
if max != 0 {
s /= max
}
v := max
return hsv{h: h, s: s, v: v}
}
type hsvTable []hsv
func toHSVTable(rgbTable []consoleColor) hsvTable {
t := make(hsvTable, len(rgbTable))
for i, c := range rgbTable {
t[i] = toHSV(c.rgb)
}
return t
}
func (t hsvTable) find(rgb int) consoleColor {
hsv := toHSV(rgb)
n := 7
l := float32(5.0)
for i, p := range t {
d := hsv.dist(p)
if d < l {
l, n = d, i
}
}
return color16[n]
}
func minmax3f(a, b, c float32) (min, max float32) {
if a < b {
if b < c {
return a, c
} else if a < c {
return a, b
} else {
return c, b
}
} else {
if a < c {
return b, c
} else if b < c {
return b, a
} else {
return c, a
}
}
}
var n256foreAttr []word
var n256backAttr []word
func n256setup() {
n256foreAttr = make([]word, 256)
n256backAttr = make([]word, 256)
t := toHSVTable(color16)
for i, rgb := range color256 {
c := t.find(rgb)
n256foreAttr[i] = c.foregroundAttr()
n256backAttr[i] = c.backgroundAttr()
}
}

View File

@ -1,55 +0,0 @@
package colorable
import (
"bytes"
"io"
)
// NonColorable hold writer but remove escape sequence.
type NonColorable struct {
out io.Writer
}
// NewNonColorable return new instance of Writer which remove escape sequence from Writer.
func NewNonColorable(w io.Writer) io.Writer {
return &NonColorable{out: w}
}
// Write write data on console
func (w *NonColorable) Write(data []byte) (n int, err error) {
er := bytes.NewReader(data)
var bw [1]byte
loop:
for {
c1, err := er.ReadByte()
if err != nil {
break loop
}
if c1 != 0x1b {
bw[0] = c1
w.out.Write(bw[:])
continue
}
c2, err := er.ReadByte()
if err != nil {
break loop
}
if c2 != 0x5b {
continue
}
var buf bytes.Buffer
for {
c, err := er.ReadByte()
if err != nil {
break loop
}
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
break
}
buf.Write([]byte(string(c)))
}
}
return len(data), nil
}

View File

@ -1 +0,0 @@
*.test

View File

@ -1,9 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 Mario L. Gutierrez
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,121 +0,0 @@
# ansi
Package ansi is a small, fast library to create ANSI colored strings and codes.
## Install
Get it
```sh
go get -u github.com/mgutz/ansi
```
## Example
```go
import "github.com/mgutz/ansi"
// colorize a string, SLOW
msg := ansi.Color("foo", "red+b:white")
// create a FAST closure function to avoid computation of ANSI code
phosphorize := ansi.ColorFunc("green+h:black")
msg = phosphorize("Bring back the 80s!")
msg2 := phospohorize("Look, I'm a CRT!")
// cache escape codes and build strings manually
lime := ansi.ColorCode("green+h:black")
reset := ansi.ColorCode("reset")
fmt.Println(lime, "Bring back the 80s!", reset)
```
Other examples
```go
Color(s, "red") // red
Color(s, "red+b") // red bold
Color(s, "red+B") // red blinking
Color(s, "red+u") // red underline
Color(s, "red+bh") // red bold bright
Color(s, "red:white") // red on white
Color(s, "red+b:white+h") // red bold on white bright
Color(s, "red+B:white+h") // red blink on white bright
Color(s, "off") // turn off ansi codes
```
To view color combinations, from project directory in terminal.
```sh
go test
```
## Style format
```go
"foregroundColor+attributes:backgroundColor+attributes"
```
Colors
* black
* red
* green
* yellow
* blue
* magenta
* cyan
* white
* 0...255 (256 colors)
Foreground Attributes
* B = Blink
* b = bold
* h = high intensity (bright)
* i = inverse
* s = strikethrough
* u = underline
Background Attributes
* h = high intensity (bright)
## Constants
* ansi.Reset
* ansi.DefaultBG
* ansi.DefaultFG
* ansi.Black
* ansi.Red
* ansi.Green
* ansi.Yellow
* ansi.Blue
* ansi.Magenta
* ansi.Cyan
* ansi.White
* ansi.LightBlack
* ansi.LightRed
* ansi.LightGreen
* ansi.LightYellow
* ansi.LightBlue
* ansi.LightMagenta
* ansi.LightCyan
* ansi.LightWhite
## References
Wikipedia ANSI escape codes [Colors](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors)
General [tips and formatting](http://misc.flogisoft.com/bash/tip_colors_and_formatting)
What about support on Windows? Use [colorable by mattn](https://github.com/mattn/go-colorable).
Ansi and colorable are used by [logxi](https://github.com/mgutz/logxi) to support logging in
color on Windows.
## MIT License
Copyright (c) 2013 Mario Gutierrez mario@mgutz.com
See the file LICENSE for copying permission.

285
vendor/github.com/mgutz/ansi/ansi.go generated vendored
View File

@ -1,285 +0,0 @@
package ansi
import (
"bytes"
"fmt"
"strconv"
"strings"
)
const (
black = iota
red
green
yellow
blue
magenta
cyan
white
defaultt = 9
normalIntensityFG = 30
highIntensityFG = 90
normalIntensityBG = 40
highIntensityBG = 100
start = "\033["
bold = "1;"
blink = "5;"
underline = "4;"
inverse = "7;"
strikethrough = "9;"
// Reset is the ANSI reset escape sequence
Reset = "\033[0m"
// DefaultBG is the default background
DefaultBG = "\033[49m"
// DefaultFG is the default foreground
DefaultFG = "\033[39m"
)
// Black FG
var Black string
// Red FG
var Red string
// Green FG
var Green string
// Yellow FG
var Yellow string
// Blue FG
var Blue string
// Magenta FG
var Magenta string
// Cyan FG
var Cyan string
// White FG
var White string
// LightBlack FG
var LightBlack string
// LightRed FG
var LightRed string
// LightGreen FG
var LightGreen string
// LightYellow FG
var LightYellow string
// LightBlue FG
var LightBlue string
// LightMagenta FG
var LightMagenta string
// LightCyan FG
var LightCyan string
// LightWhite FG
var LightWhite string
var (
plain = false
// Colors maps common color names to their ANSI color code.
Colors = map[string]int{
"black": black,
"red": red,
"green": green,
"yellow": yellow,
"blue": blue,
"magenta": magenta,
"cyan": cyan,
"white": white,
"default": defaultt,
}
)
func init() {
for i := 0; i < 256; i++ {
Colors[strconv.Itoa(i)] = i
}
Black = ColorCode("black")
Red = ColorCode("red")
Green = ColorCode("green")
Yellow = ColorCode("yellow")
Blue = ColorCode("blue")
Magenta = ColorCode("magenta")
Cyan = ColorCode("cyan")
White = ColorCode("white")
LightBlack = ColorCode("black+h")
LightRed = ColorCode("red+h")
LightGreen = ColorCode("green+h")
LightYellow = ColorCode("yellow+h")
LightBlue = ColorCode("blue+h")
LightMagenta = ColorCode("magenta+h")
LightCyan = ColorCode("cyan+h")
LightWhite = ColorCode("white+h")
}
// ColorCode returns the ANSI color color code for style.
func ColorCode(style string) string {
return colorCode(style).String()
}
// Gets the ANSI color code for a style.
func colorCode(style string) *bytes.Buffer {
buf := bytes.NewBufferString("")
if plain || style == "" {
return buf
}
if style == "reset" {
buf.WriteString(Reset)
return buf
} else if style == "off" {
return buf
}
foregroundBackground := strings.Split(style, ":")
foreground := strings.Split(foregroundBackground[0], "+")
fgKey := foreground[0]
fg := Colors[fgKey]
fgStyle := ""
if len(foreground) > 1 {
fgStyle = foreground[1]
}
bg, bgStyle := "", ""
if len(foregroundBackground) > 1 {
background := strings.Split(foregroundBackground[1], "+")
bg = background[0]
if len(background) > 1 {
bgStyle = background[1]
}
}
buf.WriteString(start)
base := normalIntensityFG
if len(fgStyle) > 0 {
if strings.Contains(fgStyle, "b") {
buf.WriteString(bold)
}
if strings.Contains(fgStyle, "B") {
buf.WriteString(blink)
}
if strings.Contains(fgStyle, "u") {
buf.WriteString(underline)
}
if strings.Contains(fgStyle, "i") {
buf.WriteString(inverse)
}
if strings.Contains(fgStyle, "s") {
buf.WriteString(strikethrough)
}
if strings.Contains(fgStyle, "h") {
base = highIntensityFG
}
}
// if 256-color
n, err := strconv.Atoi(fgKey)
if err == nil {
fmt.Fprintf(buf, "38;5;%d;", n)
} else {
fmt.Fprintf(buf, "%d;", base+fg)
}
base = normalIntensityBG
if len(bg) > 0 {
if strings.Contains(bgStyle, "h") {
base = highIntensityBG
}
// if 256-color
n, err := strconv.Atoi(bg)
if err == nil {
fmt.Fprintf(buf, "48;5;%d;", n)
} else {
fmt.Fprintf(buf, "%d;", base+Colors[bg])
}
}
// remove last ";"
buf.Truncate(buf.Len() - 1)
buf.WriteRune('m')
return buf
}
// Color colors a string based on the ANSI color code for style.
func Color(s, style string) string {
if plain || len(style) < 1 {
return s
}
buf := colorCode(style)
buf.WriteString(s)
buf.WriteString(Reset)
return buf.String()
}
// ColorFunc creates a closure to avoid computation ANSI color code.
func ColorFunc(style string) func(string) string {
if style == "" {
return func(s string) string {
return s
}
}
color := ColorCode(style)
return func(s string) string {
if plain || s == "" {
return s
}
buf := bytes.NewBufferString(color)
buf.WriteString(s)
buf.WriteString(Reset)
result := buf.String()
return result
}
}
// DisableColors disables ANSI color codes. The default is false (colors are on).
func DisableColors(disable bool) {
plain = disable
if plain {
Black = ""
Red = ""
Green = ""
Yellow = ""
Blue = ""
Magenta = ""
Cyan = ""
White = ""
LightBlack = ""
LightRed = ""
LightGreen = ""
LightYellow = ""
LightBlue = ""
LightMagenta = ""
LightCyan = ""
LightWhite = ""
} else {
Black = ColorCode("black")
Red = ColorCode("red")
Green = ColorCode("green")
Yellow = ColorCode("yellow")
Blue = ColorCode("blue")
Magenta = ColorCode("magenta")
Cyan = ColorCode("cyan")
White = ColorCode("white")
LightBlack = ColorCode("black+h")
LightRed = ColorCode("red+h")
LightGreen = ColorCode("green+h")
LightYellow = ColorCode("yellow+h")
LightBlue = ColorCode("blue+h")
LightMagenta = ColorCode("magenta+h")
LightCyan = ColorCode("cyan+h")
LightWhite = ColorCode("white+h")
}
}

65
vendor/github.com/mgutz/ansi/doc.go generated vendored
View File

@ -1,65 +0,0 @@
/*
Package ansi is a small, fast library to create ANSI colored strings and codes.
Installation
# this installs the color viewer and the package
go get -u github.com/mgutz/ansi/cmd/ansi-mgutz
Example
// colorize a string, SLOW
msg := ansi.Color("foo", "red+b:white")
// create a closure to avoid recalculating ANSI code compilation
phosphorize := ansi.ColorFunc("green+h:black")
msg = phosphorize("Bring back the 80s!")
msg2 := phospohorize("Look, I'm a CRT!")
// cache escape codes and build strings manually
lime := ansi.ColorCode("green+h:black")
reset := ansi.ColorCode("reset")
fmt.Println(lime, "Bring back the 80s!", reset)
Other examples
Color(s, "red") // red
Color(s, "red+b") // red bold
Color(s, "red+B") // red blinking
Color(s, "red+u") // red underline
Color(s, "red+bh") // red bold bright
Color(s, "red:white") // red on white
Color(s, "red+b:white+h") // red bold on white bright
Color(s, "red+B:white+h") // red blink on white bright
To view color combinations, from terminal
ansi-mgutz
Style format
"foregroundColor+attributes:backgroundColor+attributes"
Colors
black
red
green
yellow
blue
magenta
cyan
white
Attributes
b = bold foreground
B = Blink foreground
u = underline foreground
h = high intensity (bright) foreground, background
i = inverse
Wikipedia ANSI escape codes [Colors](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors)
*/
package ansi

View File

@ -1,57 +0,0 @@
package ansi
import (
"fmt"
"sort"
colorable "github.com/mattn/go-colorable"
)
// PrintStyles prints all style combinations to the terminal.
func PrintStyles() {
// for compatibility with Windows, not needed for *nix
stdout := colorable.NewColorableStdout()
bgColors := []string{
"",
":black",
":red",
":green",
":yellow",
":blue",
":magenta",
":cyan",
":white",
}
keys := make([]string, 0, len(Colors))
for k := range Colors {
keys = append(keys, k)
}
sort.Sort(sort.StringSlice(keys))
for _, fg := range keys {
for _, bg := range bgColors {
fmt.Fprintln(stdout, padColor(fg, []string{"" + bg, "+b" + bg, "+bh" + bg, "+u" + bg}))
fmt.Fprintln(stdout, padColor(fg, []string{"+s" + bg, "+i" + bg}))
fmt.Fprintln(stdout, padColor(fg, []string{"+uh" + bg, "+B" + bg, "+Bb" + bg /* backgrounds */, "" + bg + "+h"}))
fmt.Fprintln(stdout, padColor(fg, []string{"+b" + bg + "+h", "+bh" + bg + "+h", "+u" + bg + "+h", "+uh" + bg + "+h"}))
}
}
}
func pad(s string, length int) string {
for len(s) < length {
s += " "
}
return s
}
func padColor(color string, styles []string) string {
buffer := ""
for _, style := range styles {
buffer += Color(pad(color+style, 20), color+style)
}
return buffer
}

View File

@ -149,6 +149,17 @@ To add a constant, add the header that includes it to the appropriate variable.
Then, edit the regex (if necessary) to match the desired constant. Avoid making
the regex too broad to avoid matching unintended constants.
### mkmerge.go
This program is used to extract duplicate const, func, and type declarations
from the generated architecture-specific files listed below, and merge these
into a common file for each OS.
The merge is performed in the following steps:
1. Construct the set of common code that is idential in all architecture-specific files.
2. Write this common code to the merged file.
3. Remove the common code from all architecture-specific files.
## Generated files

View File

@ -486,7 +486,7 @@ ccflags="$@"
$2 ~ /^TCSET/ ||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
$2 !~ "RTF_BITS" &&
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^(IFF|IFT|NET_RT|RTM(GRP)?|RTF|RTV|RTA|RTAX)_/ ||
$2 ~ /^BIOC/ ||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||

View File

@ -529,12 +529,6 @@ func PtraceGetRegs(pid int, regsout *Reg) (err error) {
return ptrace(PTRACE_GETREGS, pid, uintptr(unsafe.Pointer(regsout)), 0)
}
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}
func PtraceLwpEvents(pid int, enable int) (err error) {
return ptrace(PTRACE_LWPEVENTS, pid, 0, enable)
}

View File

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint32(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -54,3 +54,9 @@ func sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
func PtraceIO(req int, pid int, addr uintptr, out []byte, countin int) (count int, err error) {
ioDesc := PtraceIoDesc{Op: int32(req), Offs: (*byte)(unsafe.Pointer(addr)), Addr: (*byte)(unsafe.Pointer(&out[0])), Len: uint64(countin)}
err = ptrace(PTRACE_IO, pid, uintptr(unsafe.Pointer(&ioDesc)), 0)
return int(ioDesc.Len), err
}

View File

@ -1555,8 +1555,8 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Acct(path string) (err error)
//sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error)
//sys Adjtimex(buf *Timex) (state int, err error)
//sys Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capget(hdr *CapUserHeader, data *CapUserData) (err error)
//sysnb Capset(hdr *CapUserHeader, data *CapUserData) (err error)
//sys Chdir(path string) (err error)
//sys Chroot(path string) (err error)
//sys ClockGetres(clockid int32, res *Timespec) (err error)
@ -1654,6 +1654,30 @@ func Setgid(uid int) (err error) {
return EOPNOTSUPP
}
// SetfsgidRetGid sets fsgid for current thread and returns previous fsgid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability.
// If the call fails due to other reasons, current fsgid will be returned.
func SetfsgidRetGid(gid int) (int, error) {
return setfsgid(gid)
}
// SetfsuidRetUid sets fsuid for current thread and returns previous fsuid set.
// setfsgid(2) will return a non-nil error only if its caller lacks CAP_SETUID capability
// If the call fails due to other reasons, current fsuid will be returned.
func SetfsuidRetUid(uid int) (int, error) {
return setfsuid(uid)
}
func Setfsgid(gid int) error {
_, err := setfsgid(gid)
return err
}
func Setfsuid(uid int) error {
_, err := setfsuid(uid)
return err
}
func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) {
return signalfd(fd, sigmask, _C__NSIG/8, flags)
}

View File

@ -70,8 +70,8 @@ func Pipe2(p []int, flags int) (err error) {
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
//sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32

View File

@ -55,8 +55,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -98,8 +98,8 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys Setfsgid(gid int) (err error) = SYS_SETFSGID32
//sys Setfsuid(uid int) (err error) = SYS_SETFSUID32
//sys setfsgid(gid int) (prev int, err error) = SYS_SETFSGID32
//sys setfsuid(uid int) (prev int, err error) = SYS_SETFSUID32
//sysnb Setregid(rgid int, egid int) (err error) = SYS_SETREGID32
//sysnb Setresgid(rgid int, egid int, sgid int) (err error) = SYS_SETRESGID32
//sysnb Setresuid(ruid int, euid int, suid int) (err error) = SYS_SETRESUID32

View File

@ -42,8 +42,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -36,8 +36,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
@ -216,6 +216,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -31,8 +31,8 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -34,8 +34,8 @@ package unix
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -41,8 +41,8 @@ func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err
}
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -34,8 +34,8 @@ import (
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -30,8 +30,8 @@ package unix
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sys setfsgid(gid int) (prev int, err error)
//sys setfsuid(uid int) (prev int, err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)

View File

@ -72,16 +72,20 @@ func SysctlUvmexp(name string) (*Uvmexp, error) {
return &u, nil
}
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
return Pipe2(p, 0)
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) error {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
err := pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
return err
}
//sys Getdents(fd int, buf []byte) (n int, err error)

2453
vendor/golang.org/x/sys/unix/zerrors_linux.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1825
vendor/golang.org/x/sys/unix/zsyscall_linux.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -350,8 +350,8 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]_C_int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@ -350,8 +350,8 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]_C_int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@ -350,8 +350,8 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]_C_int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@ -350,8 +350,8 @@ func Munlockall() (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func pipe(p *[2]_C_int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0)
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
err = errnoErr(e1)
}

View File

@ -297,4 +297,5 @@ const (
SYS_FSMOUNT = 432
SYS_FSPICK = 433
SYS_PIDFD_OPEN = 434
SYS_CLONE3 = 435
)

View File

@ -423,7 +423,7 @@ type PtraceIoDesc struct {
Op int32
Offs *byte
Addr *byte
Len uint
Len uint32
}
type Kevent_t struct {

View File

@ -428,7 +428,7 @@ type PtraceIoDesc struct {
Op int32
Offs *byte
Addr *byte
Len uint
Len uint64
}
type Kevent_t struct {

View File

@ -405,7 +405,7 @@ type PtraceIoDesc struct {
Op int32
Offs *byte
Addr *byte
Len uint
Len uint32
}
type Kevent_t struct {

View File

@ -406,7 +406,7 @@ type PtraceIoDesc struct {
Op int32
Offs *byte
Addr *byte
Len uint
Len uint64
}
type Kevent_t struct {

2274
vendor/golang.org/x/sys/unix/ztypes_linux.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More