mirror of
https://github.com/cheat/cheat.git
synced 2025-09-01 17:48:30 +02:00
Compare commits
151 Commits
Author | SHA1 | Date | |
---|---|---|---|
f421483eea | |||
4adddbf504 | |||
b9c86b6975 | |||
0b21ccf6f8 | |||
a3ad8c5101 | |||
bacb74929a | |||
82e1c27494 | |||
45beeb2edb | |||
c2c479b36c | |||
cb0243e7fc | |||
e5d04d41ea | |||
2474ea4fb1 | |||
7467c9fbc0 | |||
dfba3da003 | |||
ad7ad64a75 | |||
c4dcfd5da0 | |||
278a5d9154 | |||
9fa0c466fd | |||
4e9b2928b3 | |||
fa5eb44be8 | |||
49afd7c16b | |||
59d5c96c24 | |||
8e602b0e93 | |||
fb04cb1fcd | |||
d42726101e | |||
93b3a711f5 | |||
9c3d41c8bd | |||
4eeec6c868 | |||
1b17ab1914 | |||
477650ee44 | |||
c4dd3b52fd | |||
e8a0ea0dc3 | |||
992ee66a56 | |||
c9840c2d6f | |||
bd53768f67 | |||
8092687956 | |||
16ade50672 | |||
62c80d76eb | |||
3e67eaa3b7 | |||
38b13655fe | |||
749d5c1182 | |||
521f83377c | |||
b15ff10537 | |||
5288bd0c1c | |||
bddbee4158 | |||
ce27cf2cc0 | |||
5733b1d6d4 | |||
2d221050d8 | |||
ce37b670c7 | |||
47a9eeb4fd | |||
be56c9cf0c | |||
7be57cb01c | |||
8453af8601 | |||
6e388c3693 | |||
b13246978a | |||
a39d36cd34 | |||
87cba04ff2 | |||
bc623da74b | |||
a6c25d4b9c | |||
e24ac2b385 | |||
e0c35a74d4 | |||
3e4c1818a9 | |||
7b4a268ebd | |||
f7183aa17a | |||
1ce6c29e6a | |||
219db679e1 | |||
53177cb09d | |||
ef7a41f9a9 | |||
008316d030 | |||
a59c019642 | |||
57225442be | |||
2c7ce48859 | |||
a3fe4f40bb | |||
506fb8be15 | |||
408e944eea | |||
8a313b92ca | |||
6912771c39 | |||
d4c6200702 | |||
9251849d23 | |||
313b5ebd27 | |||
ca91b25b02 | |||
bbf6af50b1 | |||
9f05442bce | |||
3fc4c2f89e | |||
9e88ff2642 | |||
e3764b81e7 | |||
3786ac96a5 | |||
4cb7a3b42c | |||
ff6a866abe | |||
2e7ccb2a68 | |||
126231db1f | |||
91f0d02de2 | |||
815e714fb4 | |||
bd3986a051 | |||
f47b75edc0 | |||
180ee20f77 | |||
9b86c583f8 | |||
e1f7828869 | |||
7f3ae2ab30 | |||
bbd03a1bb8 | |||
326c54147b | |||
efcedaedec | |||
301cbefb0c | |||
9a481f7e75 | |||
e2920bd922 | |||
973a1f59ea | |||
3afea0972c | |||
f86633ca1c | |||
a01a3491a4 | |||
daa43d3867 | |||
e94a1e22df | |||
5046975a0f | |||
198156a299 | |||
a7067279df | |||
a8e6fdb18a | |||
bbfa4efdb7 | |||
741ad91389 | |||
573d43a7e6 | |||
879e8f2be4 | |||
eab3c14f1f | |||
9a6130b6b7 | |||
aeaf01e1de | |||
09c29a322f | |||
0525b2331b | |||
27a4991a3a | |||
4dda412dcb | |||
bfb60764ad | |||
3a97c680bb | |||
edc0fe41ef | |||
9e49bf8e9c | |||
50dc3c8b29 | |||
e08a4f3cec | |||
d6ebe0799d | |||
51aaaf3423 | |||
197ff58796 | |||
b8f512aae8 | |||
e7a1a296e3 | |||
f7c093bec0 | |||
c47b7f81aa | |||
52081b97ac | |||
1dda796e7c | |||
67469b0afa | |||
4f8431a600 | |||
5301442f7c | |||
cd45efcdec | |||
c31786fc5b | |||
934c36ad77 | |||
2c0099c28a | |||
749173f1f6 | |||
33e33dc7b7 | |||
201cd1d629 |
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Submit a bug report
|
||||||
|
title: ''
|
||||||
|
labels: 'bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thanks for submitting a bug report. Please provide the following information:
|
||||||
|
|
||||||
|
**A description of the problem**
|
||||||
|
Describe the problem here.
|
||||||
|
|
||||||
|
**cheat version info**
|
||||||
|
Please paste the output of `cheat -v` here.
|
||||||
|
|
||||||
|
**cheat configuration info**
|
||||||
|
If your bug pertains to how cheatsheets are loaded and/or displayed, please
|
||||||
|
paste here the following information:
|
||||||
|
|
||||||
|
1. The output of `cheat -d`
|
||||||
|
2. The contents of your `conf.yml` file
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: 'enhancement'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
66
.github/workflows/codeql-analysis.yml
vendored
Normal file
66
.github/workflows/codeql-analysis.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
# ******** NOTE ********
|
||||||
|
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ master ]
|
||||||
|
schedule:
|
||||||
|
- cron: '45 23 * * 0'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'go' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||||
|
# Learn more...
|
||||||
|
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
#- name: Autobuild
|
||||||
|
#uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
- run: make
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
17
.github/workflows/homebrew.yml
vendored
Normal file
17
.github/workflows/homebrew.yml
vendored
Normal 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 }}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
dist
|
dist
|
||||||
|
tags
|
||||||
|
13
.travis.yml
13
.travis.yml
@ -1,4 +1,15 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.13.x
|
- 1.14.x
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
env:
|
||||||
|
- GO111MODULE=on
|
||||||
|
|
||||||
|
install: true
|
||||||
|
|
||||||
|
script: make ci
|
||||||
|
175
Makefile
Normal file
175
Makefile
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
# paths
|
||||||
|
makefile := $(realpath $(lastword $(MAKEFILE_LIST)))
|
||||||
|
cmd_dir := ./cmd/cheat
|
||||||
|
dist_dir := ./dist
|
||||||
|
|
||||||
|
# executables
|
||||||
|
CAT := cat
|
||||||
|
COLUMN := column
|
||||||
|
CTAGS := ctags
|
||||||
|
GO := go
|
||||||
|
GREP := grep
|
||||||
|
GZIP := gzip --best
|
||||||
|
LINT := revive
|
||||||
|
MAN := man
|
||||||
|
MKDIR := mkdir -p
|
||||||
|
PANDOC := pandoc
|
||||||
|
RM := rm
|
||||||
|
SCC := scc
|
||||||
|
SED := sed
|
||||||
|
SORT := sort
|
||||||
|
ZIP := zip -m
|
||||||
|
|
||||||
|
# build flags
|
||||||
|
BUILD_FLAGS := -ldflags="-s -w" -mod vendor -trimpath
|
||||||
|
GOBIN :=
|
||||||
|
TMPDIR := /tmp
|
||||||
|
|
||||||
|
# release binaries
|
||||||
|
releases := \
|
||||||
|
$(dist_dir)/cheat-darwin-amd64 \
|
||||||
|
$(dist_dir)/cheat-linux-386 \
|
||||||
|
$(dist_dir)/cheat-linux-amd64 \
|
||||||
|
$(dist_dir)/cheat-linux-arm5 \
|
||||||
|
$(dist_dir)/cheat-linux-arm6 \
|
||||||
|
$(dist_dir)/cheat-linux-arm7 \
|
||||||
|
$(dist_dir)/cheat-windows-amd64.exe
|
||||||
|
|
||||||
|
## build: build an executable for your architecture
|
||||||
|
.PHONY: build
|
||||||
|
build: $(dist_dir) clean vendor generate man
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $(dist_dir)/cheat $(cmd_dir)
|
||||||
|
|
||||||
|
## build-release: build release executables
|
||||||
|
.PHONY: build-release
|
||||||
|
build-release: $(releases)
|
||||||
|
|
||||||
|
## ci: build a "release" executable for the current architecture (used in ci)
|
||||||
|
.PHONY: ci
|
||||||
|
ci: | setup prepare build
|
||||||
|
|
||||||
|
# cheat-darwin-amd64
|
||||||
|
$(dist_dir)/cheat-darwin-amd64: prepare
|
||||||
|
GOARCH=amd64 GOOS=darwin \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-linux-386
|
||||||
|
$(dist_dir)/cheat-linux-386: prepare
|
||||||
|
GOARCH=386 GOOS=linux \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-linux-amd64
|
||||||
|
$(dist_dir)/cheat-linux-amd64: prepare
|
||||||
|
GOARCH=amd64 GOOS=linux \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-linux-arm5
|
||||||
|
$(dist_dir)/cheat-linux-arm5: prepare
|
||||||
|
GOARCH=arm GOOS=linux GOARM=5 \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-linux-arm6
|
||||||
|
$(dist_dir)/cheat-linux-arm6: prepare
|
||||||
|
GOARCH=arm GOOS=linux GOARM=6 \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-linux-arm7
|
||||||
|
$(dist_dir)/cheat-linux-arm7: prepare
|
||||||
|
GOARCH=arm GOOS=linux GOARM=7 \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(GZIP) $@ && chmod -x $@.gz
|
||||||
|
|
||||||
|
# cheat-windows-amd64
|
||||||
|
$(dist_dir)/cheat-windows-amd64.exe: prepare
|
||||||
|
GOARCH=amd64 GOOS=windows \
|
||||||
|
$(GO) build $(BUILD_FLAGS) -o $@ $(cmd_dir) && $(ZIP) $@.zip $@
|
||||||
|
|
||||||
|
# ./dist
|
||||||
|
$(dist_dir):
|
||||||
|
$(MKDIR) $(dist_dir)
|
||||||
|
|
||||||
|
.PHONY: generate
|
||||||
|
generate:
|
||||||
|
$(GO) generate $(cmd_dir)
|
||||||
|
|
||||||
|
## install: build and install cheat on your PATH
|
||||||
|
.PHONY: install
|
||||||
|
install: build
|
||||||
|
$(GO) install $(BUILD_FLAGS) $(GOBIN) $(cmd_dir)
|
||||||
|
|
||||||
|
## clean: remove compiled executables
|
||||||
|
.PHONY: clean
|
||||||
|
clean: $(dist_dir)
|
||||||
|
$(RM) -f $(dist_dir)/*
|
||||||
|
|
||||||
|
## distclean: remove the tags file
|
||||||
|
.PHONY: distclean
|
||||||
|
distclean:
|
||||||
|
$(RM) -f tags
|
||||||
|
|
||||||
|
## 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: count "semantic lines of code"
|
||||||
|
.PHONY: sloc
|
||||||
|
sloc:
|
||||||
|
$(SCC) --exclude-dir=vendor
|
||||||
|
|
||||||
|
## tags: build a tags file
|
||||||
|
.PHONY: tags
|
||||||
|
tags:
|
||||||
|
$(CTAGS) -R --exclude=vendor --languages=go
|
||||||
|
|
||||||
|
## 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: run go fmt
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
$(GO) fmt ./...
|
||||||
|
|
||||||
|
## lint: lint go source files
|
||||||
|
.PHONY: lint
|
||||||
|
lint: vendor
|
||||||
|
$(LINT) -exclude vendor/... ./...
|
||||||
|
|
||||||
|
## vet: vet go source files
|
||||||
|
.PHONY: vet
|
||||||
|
vet:
|
||||||
|
$(GO) vet ./...
|
||||||
|
|
||||||
|
## test: run unit-tests
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
$(GO) test ./...
|
||||||
|
|
||||||
|
## 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: 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: display this help text
|
||||||
|
.PHONY: help
|
||||||
|
help:
|
||||||
|
@$(CAT) $(makefile) | \
|
||||||
|
$(SORT) | \
|
||||||
|
$(GREP) "^##" | \
|
||||||
|
$(SED) 's/## //g' | \
|
||||||
|
$(COLUMN) -t -s ':'
|
31
README.md
31
README.md
@ -51,7 +51,9 @@ Installing
|
|||||||
Configuring
|
Configuring
|
||||||
-----------
|
-----------
|
||||||
### conf.yml ###
|
### 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
|
```sh
|
||||||
mkdir -p ~/.config/cheat && cheat --init > ~/.config/cheat/conf.yml
|
mkdir -p ~/.config/cheat && cheat --init > ~/.config/cheat/conf.yml
|
||||||
@ -89,13 +91,14 @@ const squares = [1, 2, 3, 4].map(x => x * x);
|
|||||||
```
|
```
|
||||||
|
|
||||||
The `cheat` executable includes no cheatsheets, but [community-sourced
|
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
|
Cheatpaths
|
||||||
----------
|
----------
|
||||||
Cheatsheets are stored on "cheatpaths", which are directories that contain
|
Cheatsheets are stored on "cheatpaths", which are directories that contain
|
||||||
cheetsheets. Cheatpaths are specified in the `conf.yml` file.
|
cheatsheets. Cheatpaths are specified in the `conf.yml` file.
|
||||||
|
|
||||||
It can be useful to configure `cheat` against multiple cheatpaths. A common
|
It can be useful to configure `cheat` against multiple cheatpaths. A common
|
||||||
pattern is to store cheatsheets from multiple repositories on individual
|
pattern is to store cheatsheets from multiple repositories on individual
|
||||||
@ -125,6 +128,11 @@ If a user attempts to edit a cheatsheet on a read-only cheatpath, `cheat` will
|
|||||||
transparently copy that sheet to a writeable directory before opening it for
|
transparently copy that sheet to a writeable directory before opening it for
|
||||||
editing.
|
editing.
|
||||||
|
|
||||||
|
### Directory-scoped Cheatpaths ###
|
||||||
|
At times, it can be useful to closely associate cheatsheets with a directory on
|
||||||
|
your filesystem. `cheat` facilitates this by searching for a `.cheat` folder in
|
||||||
|
the current working directory. If found, the `.cheat` directory will
|
||||||
|
(temporarily) be added to the cheatpaths.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
@ -178,21 +186,28 @@ To search (by regex) for cheatsheets that contain an IP address:
|
|||||||
cheat -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
```
|
```
|
||||||
|
|
||||||
Flags may be combined in inuitive ways. Example: to search sheets on the
|
Flags may be combined in intuitive ways. Example: to search sheets on the
|
||||||
"personal" cheatpath that are tagged with "networking" and match a regex:
|
"personal" cheatpath that are tagged with "networking" and match a regex:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cheat -p personal -t networking -s --regex '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -p personal -t networking --regex -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Advanced Usage
|
Advanced Usage
|
||||||
--------------
|
--------------
|
||||||
`cheat` may be integrated with [fzf][]. See [fzf.bash][bash] for instructions.
|
Shell autocompletion is currently available for `bash`, `fish`, and `zsh`. Copy
|
||||||
(Support for other shells will be added in future releases.)
|
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][]. To enable `fzf` integration:
|
||||||
|
|
||||||
|
1. Ensure that `fzf` is available on your `$PATH`
|
||||||
|
2. Set an envvar: `export CHEAT_USE_FZF=true`
|
||||||
|
|
||||||
[Releases]: https://github.com/cheat/cheat/releases
|
[Releases]: https://github.com/cheat/cheat/releases
|
||||||
[bash]: https://github.com/cheat/cheat/blob/master/scripts/fzf.bash
|
|
||||||
[cheatsheets]: https://github.com/cheat/cheatsheets
|
[cheatsheets]: https://github.com/cheat/cheatsheets
|
||||||
|
[completions]: https://github.com/cheat/cheat/tree/master/scripts
|
||||||
[fzf]: https://github.com/junegunn/fzf
|
[fzf]: https://github.com/junegunn/fzf
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# locate the cheat project root
|
|
||||||
BINDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
APPDIR=$(readlink -f "$BINDIR/..")
|
|
||||||
|
|
||||||
# compile the executable
|
|
||||||
cd "$APPDIR/cmd/cheat"
|
|
||||||
go clean && go generate && go build -mod vendor
|
|
||||||
mv "$APPDIR/cmd/cheat/cheat" "$APPDIR/dist/cheat"
|
|
||||||
|
|
||||||
# display a build checksum
|
|
||||||
md5sum "$APPDIR/dist/cheat"
|
|
@ -1,19 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# locate the cheat project root
|
|
||||||
BINDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
APPDIR=$(readlink -f "$BINDIR/..")
|
|
||||||
|
|
||||||
# build embeds
|
|
||||||
cd "$APPDIR/cmd/cheat"
|
|
||||||
go clean && go generate
|
|
||||||
|
|
||||||
# compile AMD64 for Linux, OSX, and Windows
|
|
||||||
env GOOS=darwin GOARCH=amd64 go build -mod vendor -o \
|
|
||||||
"$APPDIR/dist/cheat-darwin-amd64" "$APPDIR/cmd/cheat"
|
|
||||||
|
|
||||||
env GOOS=linux GOARCH=amd64 go build -mod vendor -o \
|
|
||||||
"$APPDIR/dist/cheat-linux-amd64" "$APPDIR/cmd/cheat"
|
|
||||||
|
|
||||||
env GOOS=windows GOARCH=amd64 go build -mod vendor -o \
|
|
||||||
"$APPDIR/dist/cheat-win-amd64.exe" "$APPDIR/cmd/cheat"
|
|
@ -1,18 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/display"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmdDirectories lists the configured cheatpaths.
|
// cmdDirectories lists the configured cheatpaths.
|
||||||
func cmdDirectories(opts map[string]interface{}, conf config.Config) {
|
func cmdDirectories(opts map[string]interface{}, conf config.Config) {
|
||||||
|
|
||||||
// initialize a tabwriter to produce cleanly columnized output
|
// initialize a tabwriter to produce cleanly columnized output
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
|
var out bytes.Buffer
|
||||||
|
w := tabwriter.NewWriter(&out, 0, 0, 1, ' ', 0)
|
||||||
|
|
||||||
// generate sorted, columnized output
|
// generate sorted, columnized output
|
||||||
for _, path := range conf.Cheatpaths {
|
for _, path := range conf.Cheatpaths {
|
||||||
@ -25,4 +27,5 @@ func cmdDirectories(opts map[string]interface{}, conf config.Config) {
|
|||||||
|
|
||||||
// write columnized output to stdout
|
// write columnized output to stdout
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
display.Display(out.String(), conf)
|
||||||
}
|
}
|
||||||
|
@ -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
|
// edit the cheatsheet
|
||||||
cmd := exec.Command(conf.Editor, editpath)
|
cmd := exec.Command(editor, args...)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stdin = os.Stdin
|
cmd.Stdin = os.Stdin
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
@ -2,9 +2,56 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cmdInit displays an example config file.
|
// cmdInit displays an example config file.
|
||||||
func cmdInit() {
|
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)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/display"
|
||||||
"github.com/cheat/cheat/internal/sheet"
|
"github.com/cheat/cheat/internal/sheet"
|
||||||
"github.com/cheat/cheat/internal/sheets"
|
"github.com/cheat/cheat/internal/sheets"
|
||||||
)
|
)
|
||||||
@ -45,16 +48,52 @@ func cmdList(opts map[string]interface{}, conf config.Config) {
|
|||||||
return flattened[i].Title < flattened[j].Title
|
return flattened[i].Title < flattened[j].Title
|
||||||
})
|
})
|
||||||
|
|
||||||
// exit early if no cheatsheets are available
|
// filter if <cheatsheet> was specified
|
||||||
|
// NB: our docopt specification is misleading here. When used in conjunction
|
||||||
|
// with `-l`, `<cheatsheet>` is really a pattern against which to filter
|
||||||
|
// sheet titles.
|
||||||
|
if opts["<cheatsheet>"] != nil {
|
||||||
|
|
||||||
|
// initialize a slice of filtered sheets
|
||||||
|
filtered := []sheet.Sheet{}
|
||||||
|
|
||||||
|
// initialize our filter pattern
|
||||||
|
pattern := "(?i)" + opts["<cheatsheet>"].(string)
|
||||||
|
|
||||||
|
// compile the regex
|
||||||
|
reg, err := regexp.Compile(pattern)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(
|
||||||
|
os.Stderr,
|
||||||
|
fmt.Sprintf("failed to compile regexp: %s, %v", pattern, err),
|
||||||
|
)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over each cheatsheet, and pass-through those which match the
|
||||||
|
// filter pattern
|
||||||
|
for _, s := range flattened {
|
||||||
|
if reg.MatchString(s.Title) {
|
||||||
|
filtered = append(filtered, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flattened = filtered
|
||||||
|
}
|
||||||
|
|
||||||
|
// return exit code 2 if no cheatsheets are available
|
||||||
if len(flattened) == 0 {
|
if len(flattened) == 0 {
|
||||||
os.Exit(0)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize a tabwriter to produce cleanly columnized output
|
// initialize a tabwriter to produce cleanly columnized output
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
|
var out bytes.Buffer
|
||||||
|
w := tabwriter.NewWriter(&out, 0, 0, 1, ' ', 0)
|
||||||
|
|
||||||
|
// write a header row
|
||||||
|
fmt.Fprintln(w, "title:\tfile:\ttags:")
|
||||||
|
|
||||||
// generate sorted, columnized output
|
// generate sorted, columnized output
|
||||||
fmt.Fprintln(w, "title:\tfile:\ttags:")
|
|
||||||
for _, sheet := range flattened {
|
for _, sheet := range flattened {
|
||||||
fmt.Fprintln(w, fmt.Sprintf(
|
fmt.Fprintln(w, fmt.Sprintf(
|
||||||
"%s\t%s\t%s",
|
"%s\t%s\t%s",
|
||||||
@ -66,4 +105,5 @@ func cmdList(opts map[string]interface{}, conf config.Config) {
|
|||||||
|
|
||||||
// write columnized output to stdout
|
// write columnized output to stdout
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
display.Display(out.String(), conf)
|
||||||
}
|
}
|
||||||
|
55
cmd/cheat/cmd_remove.go
Normal file
55
cmd/cheat/cmd_remove.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/sheets"
|
||||||
|
)
|
||||||
|
|
||||||
|
// cmdRemove opens a cheatsheet for editing (or creates it if it doesn't exist).
|
||||||
|
func cmdRemove(opts map[string]interface{}, conf config.Config) {
|
||||||
|
|
||||||
|
cheatsheet := opts["--rm"].(string)
|
||||||
|
|
||||||
|
// load the cheatsheets
|
||||||
|
cheatsheets, err := sheets.Load(conf.Cheatpaths)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to list cheatsheets: %v", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter cheatcheats by tag if --tag was provided
|
||||||
|
if opts["--tag"] != nil {
|
||||||
|
cheatsheets = sheets.Filter(
|
||||||
|
cheatsheets,
|
||||||
|
strings.Split(opts["--tag"].(string), ","),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// consolidate the cheatsheets found on all paths into a single map of
|
||||||
|
// `title` => `sheet` (ie, allow more local cheatsheets to override less
|
||||||
|
// local cheatsheets)
|
||||||
|
consolidated := sheets.Consolidate(cheatsheets)
|
||||||
|
|
||||||
|
// fail early if the requested cheatsheet does not exist
|
||||||
|
sheet, ok := consolidated[cheatsheet]
|
||||||
|
if !ok {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("No cheatsheet found for '%s'.\n", cheatsheet))
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail early if the sheet is read-only
|
||||||
|
if sheet.ReadOnly {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("cheatsheet '%s' is read-only.", cheatsheet))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, attempt to delete the sheet
|
||||||
|
if err := os.Remove(sheet.Path); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to delete sheet: %s, %v", sheet.Title, err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/display"
|
||||||
|
"github.com/cheat/cheat/internal/sheet"
|
||||||
"github.com/cheat/cheat/internal/sheets"
|
"github.com/cheat/cheat/internal/sheets"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,15 +37,27 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
|
|||||||
// local cheatsheets)
|
// local cheatsheets)
|
||||||
consolidated := sheets.Consolidate(cheatsheets)
|
consolidated := sheets.Consolidate(cheatsheets)
|
||||||
|
|
||||||
// sort the cheatsheets alphabetically, and search for matches
|
// if <cheatsheet> was provided, search that single sheet only
|
||||||
for _, sheet := range sheets.Sort(consolidated) {
|
if opts["<cheatsheet>"] != nil {
|
||||||
|
|
||||||
// colorize output?
|
cheatsheet := opts["<cheatsheet>"].(string)
|
||||||
colorize := false
|
|
||||||
if conf.Colorize == true || opts["--colorize"] == true {
|
// assert that the cheatsheet exists
|
||||||
colorize = true
|
s, ok := consolidated[cheatsheet]
|
||||||
|
if !ok {
|
||||||
|
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
|
||||||
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consolidated = map[string]sheet.Sheet{
|
||||||
|
cheatsheet: s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the cheatsheets alphabetically, and search for matches
|
||||||
|
out := ""
|
||||||
|
for _, sheet := range sheets.Sort(consolidated) {
|
||||||
|
|
||||||
// assume that we want to perform a case-insensitive search for <phrase>
|
// assume that we want to perform a case-insensitive search for <phrase>
|
||||||
pattern := "(?i)" + phrase
|
pattern := "(?i)" + phrase
|
||||||
|
|
||||||
@ -55,21 +69,34 @@ func cmdSearch(opts map[string]interface{}, conf config.Config) {
|
|||||||
// compile the regex
|
// compile the regex
|
||||||
reg, err := regexp.Compile(pattern)
|
reg, err := regexp.Compile(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("failed to compile regexp: %s, %v", pattern, err)
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to compile regexp: %s, %v", pattern, err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// search the sheet
|
// `Search` will return text entries that match the search terms. We're
|
||||||
matches := sheet.Search(reg, colorize)
|
// 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 the sheet did not match the search, ignore it and move on
|
||||||
if len(matches) > 0 {
|
if sheet.Text == "" {
|
||||||
fmt.Printf("%s:\n", sheet.Title)
|
continue
|
||||||
for _, m := range matches {
|
|
||||||
fmt.Printf(" %d: %s\n", m.Line, m.Text)
|
|
||||||
}
|
}
|
||||||
fmt.Print("\n")
|
|
||||||
|
// if colorization was requested, apply it here
|
||||||
|
if conf.Color(opts) {
|
||||||
|
sheet.Colorize(conf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// output the cheatsheet title
|
||||||
|
out += fmt.Sprintf("%s:\n", sheet.Title)
|
||||||
|
|
||||||
|
// indent each line of content with two spaces
|
||||||
|
for _, line := range strings.Split(sheet.Text, "\n") {
|
||||||
|
out += fmt.Sprintf(" %s\n", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// display the output
|
||||||
|
display.Display(out, conf)
|
||||||
}
|
}
|
||||||
|
30
cmd/cheat/cmd_tags.go
Normal file
30
cmd/cheat/cmd_tags.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/display"
|
||||||
|
"github.com/cheat/cheat/internal/sheets"
|
||||||
|
)
|
||||||
|
|
||||||
|
// cmdTags lists all tags in use.
|
||||||
|
func cmdTags(opts map[string]interface{}, conf config.Config) {
|
||||||
|
|
||||||
|
// load the cheatsheets
|
||||||
|
cheatsheets, err := sheets.Load(conf.Cheatpaths)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to list cheatsheets: %v", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// assemble the output
|
||||||
|
out := ""
|
||||||
|
for _, tag := range sheets.Tags(cheatsheets) {
|
||||||
|
out += fmt.Sprintln(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// display the output
|
||||||
|
display.Display(out, conf)
|
||||||
|
}
|
@ -5,10 +5,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/chroma/quick"
|
|
||||||
"github.com/mattn/go-isatty"
|
|
||||||
|
|
||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/display"
|
||||||
"github.com/cheat/cheat/internal/sheets"
|
"github.com/cheat/cheat/internal/sheets"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,45 +39,14 @@ func cmdView(opts map[string]interface{}, conf config.Config) {
|
|||||||
sheet, ok := consolidated[cheatsheet]
|
sheet, ok := consolidated[cheatsheet]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
|
fmt.Printf("No cheatsheet found for '%s'.\n", cheatsheet)
|
||||||
os.Exit(0)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply colorization if so configured ...
|
// apply colorization if requested
|
||||||
colorize := conf.Colorize
|
if conf.Color(opts) {
|
||||||
|
sheet.Colorize(conf)
|
||||||
// ... or if --colorized were passed ...
|
|
||||||
if opts["--colorize"] == true {
|
|
||||||
colorize = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... unless we're outputting to a non-TTY
|
// display the cheatsheet
|
||||||
if !isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
display.Display(sheet.Text, conf)
|
||||||
colorize = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !colorize {
|
|
||||||
fmt.Print(sheet.Text)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,15 @@ Options:
|
|||||||
--init Write a default config file to stdout
|
--init Write a default config file to stdout
|
||||||
-c --colorize Colorize output
|
-c --colorize Colorize output
|
||||||
-d --directories List cheatsheet directories
|
-d --directories List cheatsheet directories
|
||||||
-e --edit=<sheet> Edit cheatsheet
|
-e --edit=<cheatsheet> Edit <cheatsheet>
|
||||||
-l --list List cheatsheets
|
-l --list List cheatsheets
|
||||||
-p --path=<name> Return only sheets found on path <name>
|
-p --path=<name> Return only sheets found on path <name>
|
||||||
-r --regex Treat search <phrase> as a regex
|
-r --regex Treat search <phrase> as a regex
|
||||||
-s --search=<phrase> Search cheatsheets for <phrase>
|
-s --search=<phrase> Search cheatsheets for <phrase>
|
||||||
-t --tag=<tag> Return only sheets matching <tag>
|
-t --tag=<tag> Return only sheets matching <tag>
|
||||||
|
-T --tags List all tags in use
|
||||||
-v --version Print the version number
|
-v --version Print the version number
|
||||||
|
--rm=<cheatsheet> Remove (delete) <cheatsheet>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -33,6 +35,12 @@ Examples:
|
|||||||
To list all available cheatsheets:
|
To list all available cheatsheets:
|
||||||
cheat -l
|
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":
|
To list available cheatsheets that are tagged as "personal":
|
||||||
cheat -l -t personal
|
cheat -l -t personal
|
||||||
|
|
||||||
@ -41,3 +49,6 @@ Examples:
|
|||||||
|
|
||||||
To search (by regex) for cheatsheets that contain an IP address:
|
To search (by regex) for cheatsheets that contain an IP address:
|
||||||
cheat -c -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -c -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
|
|
||||||
|
To remove (delete) the foo/bar cheatsheet:
|
||||||
|
cheat --rm foo/bar
|
||||||
|
@ -5,15 +5,19 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/docopt/docopt-go"
|
"github.com/docopt/docopt-go"
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
|
|
||||||
"github.com/cheat/cheat/internal/cheatpath"
|
"github.com/cheat/cheat/internal/cheatpath"
|
||||||
"github.com/cheat/cheat/internal/config"
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
"github.com/cheat/cheat/internal/installer"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "3.0.3"
|
const version = "4.1.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
@ -31,15 +35,108 @@ func main() {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the config file
|
// get the user's home directory
|
||||||
confpath, err := config.Path(runtime.GOOS)
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "could not locate config file")
|
fmt.Fprintf(os.Stderr, "failed to get user home directory: %v\n", err)
|
||||||
os.Exit(1)
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(confpath, configs); err != nil {
|
||||||
|
fmt.Fprintf(
|
||||||
|
os.Stderr,
|
||||||
|
"failed to create config file: %s: %v\n",
|
||||||
|
confpath,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Created config file: %s\n", confpath)
|
||||||
|
fmt.Println("Please read this file for advanced configuration information.")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
// initialize the configs
|
// initialize the configs
|
||||||
conf, err := config.New(opts, confpath)
|
conf, err := config.New(opts, confpath, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -76,12 +173,21 @@ func main() {
|
|||||||
case opts["--list"].(bool):
|
case opts["--list"].(bool):
|
||||||
cmd = cmdList
|
cmd = cmdList
|
||||||
|
|
||||||
|
case opts["--tags"].(bool):
|
||||||
|
cmd = cmdTags
|
||||||
|
|
||||||
case opts["--search"] != nil:
|
case opts["--search"] != nil:
|
||||||
cmd = cmdSearch
|
cmd = cmdSearch
|
||||||
|
|
||||||
|
case opts["--rm"] != nil:
|
||||||
|
cmd = cmdRemove
|
||||||
|
|
||||||
case opts["<cheatsheet>"] != nil:
|
case opts["<cheatsheet>"] != nil:
|
||||||
cmd = cmdView
|
cmd = cmdView
|
||||||
|
|
||||||
|
case opts["--tag"] != nil && opts["--tag"].(string) != "":
|
||||||
|
cmd = cmdList
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Println(usage())
|
fmt.Println(usage())
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
@ -23,6 +23,9 @@ style: monokai
|
|||||||
# One of: "terminal", "terminal256", "terminal16m"
|
# One of: "terminal", "terminal256", "terminal16m"
|
||||||
formatter: terminal16m
|
formatter: terminal16m
|
||||||
|
|
||||||
|
# Through which pager should output be piped? (Unset this key for no pager.)
|
||||||
|
pager: less -FRX
|
||||||
|
|
||||||
# The paths at which cheatsheets are available. Tags associated with a cheatpath
|
# The paths at which cheatsheets are available. Tags associated with a cheatpath
|
||||||
# are automatically attached to all cheatsheets residing on that path.
|
# are automatically attached to all cheatsheets residing on that path.
|
||||||
#
|
#
|
||||||
@ -32,34 +35,46 @@ formatter: terminal16m
|
|||||||
# "upstream" cheatsheets.
|
# "upstream" cheatsheets.
|
||||||
#
|
#
|
||||||
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
||||||
# Cheatsheets may be filtered via 'cheat -f <tag>' in combination with other
|
# Cheatsheets may be filtered via 'cheat -t <tag>' in combination with other
|
||||||
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
||||||
# 'community' rather than your own, you can use: cheat tar -f community
|
# 'community' rather than your own, you can use: cheat tar -t community
|
||||||
cheatpaths:
|
cheatpaths:
|
||||||
|
|
||||||
# Paths that come earlier are considered to be the most "global", and will
|
# Paths that come earlier are considered to be the most "global", and will
|
||||||
# thus be overridden by more local cheatsheets. That being the case, you
|
# thus be overridden by more local cheatsheets. That being the case, you
|
||||||
# should probably list community cheatsheets first.
|
# 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.
|
# change them to suit your needs.
|
||||||
|
#
|
||||||
|
# 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
|
- name: community
|
||||||
path: ~/.dotfiles/cheat/community
|
path: COMMUNITY_PATH
|
||||||
tags: [ community ]
|
tags: [ community ]
|
||||||
readonly: true
|
readonly: true
|
||||||
|
|
||||||
# Maybe your company or department maintains a repository of cheatsheets as
|
|
||||||
# well. It's probably sensible to list those second.
|
|
||||||
- name: work
|
|
||||||
path: ~/.dotfiles/cheat/work
|
|
||||||
tags: [ work ]
|
|
||||||
readonly: false
|
|
||||||
|
|
||||||
# If you have personalized cheatsheets, list them last. They will take
|
# If you have personalized cheatsheets, list them last. They will take
|
||||||
# precedence over the more global cheatsheets.
|
# precedence over the more global cheatsheets.
|
||||||
- name: personal
|
- name: personal
|
||||||
path: ~/.dotfiles/cheat/personal
|
path: PERSONAL_PATH
|
||||||
tags: [ personal ]
|
tags: [ personal ]
|
||||||
readonly: false
|
readonly: false
|
||||||
|
|
||||||
|
# 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,
|
||||||
|
# directory-scoped cheatsheets will always be editable ('readonly: false').
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,15 @@ Options:
|
|||||||
--init Write a default config file to stdout
|
--init Write a default config file to stdout
|
||||||
-c --colorize Colorize output
|
-c --colorize Colorize output
|
||||||
-d --directories List cheatsheet directories
|
-d --directories List cheatsheet directories
|
||||||
-e --edit=<sheet> Edit cheatsheet
|
-e --edit=<cheatsheet> Edit <cheatsheet>
|
||||||
-l --list List cheatsheets
|
-l --list List cheatsheets
|
||||||
-p --path=<name> Return only sheets found on path <name>
|
-p --path=<name> Return only sheets found on path <name>
|
||||||
-r --regex Treat search <phrase> as a regex
|
-r --regex Treat search <phrase> as a regex
|
||||||
-s --search=<phrase> Search cheatsheets for <phrase>
|
-s --search=<phrase> Search cheatsheets for <phrase>
|
||||||
-t --tag=<tag> Return only sheets matching <tag>
|
-t --tag=<tag> Return only sheets matching <tag>
|
||||||
|
-T --tags List all tags in use
|
||||||
-v --version Print the version number
|
-v --version Print the version number
|
||||||
|
--rm=<cheatsheet> Remove (delete) <cheatsheet>
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@ -42,6 +44,12 @@ Examples:
|
|||||||
To list all available cheatsheets:
|
To list all available cheatsheets:
|
||||||
cheat -l
|
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":
|
To list available cheatsheets that are tagged as "personal":
|
||||||
cheat -l -t personal
|
cheat -l -t personal
|
||||||
|
|
||||||
@ -50,5 +58,8 @@ Examples:
|
|||||||
|
|
||||||
To search (by regex) for cheatsheets that contain an IP address:
|
To search (by regex) for cheatsheets that contain an IP address:
|
||||||
cheat -c -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
cheat -c -r -s '(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
|
|
||||||
|
To remove (delete) the foo/bar cheatsheet:
|
||||||
|
cheat --rm foo/bar
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,9 @@ style: monokai
|
|||||||
# One of: "terminal", "terminal256", "terminal16m"
|
# One of: "terminal", "terminal256", "terminal16m"
|
||||||
formatter: terminal16m
|
formatter: terminal16m
|
||||||
|
|
||||||
|
# Through which pager should output be piped? (Unset this key for no pager.)
|
||||||
|
pager: less -FRX
|
||||||
|
|
||||||
# The paths at which cheatsheets are available. Tags associated with a cheatpath
|
# The paths at which cheatsheets are available. Tags associated with a cheatpath
|
||||||
# are automatically attached to all cheatsheets residing on that path.
|
# are automatically attached to all cheatsheets residing on that path.
|
||||||
#
|
#
|
||||||
@ -23,32 +26,44 @@ formatter: terminal16m
|
|||||||
# "upstream" cheatsheets.
|
# "upstream" cheatsheets.
|
||||||
#
|
#
|
||||||
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
# But what if you want to view the "upstream" cheatsheets instead of your own?
|
||||||
# Cheatsheets may be filtered via 'cheat -f <tag>' in combination with other
|
# Cheatsheets may be filtered via 'cheat -t <tag>' in combination with other
|
||||||
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
# commands. So, if you want to view the 'tar' cheatsheet that is tagged as
|
||||||
# 'community' rather than your own, you can use: cheat tar -f community
|
# 'community' rather than your own, you can use: cheat tar -t community
|
||||||
cheatpaths:
|
cheatpaths:
|
||||||
|
|
||||||
# Paths that come earlier are considered to be the most "global", and will
|
# Paths that come earlier are considered to be the most "global", and will
|
||||||
# thus be overridden by more local cheatsheets. That being the case, you
|
# thus be overridden by more local cheatsheets. That being the case, you
|
||||||
# should probably list community cheatsheets first.
|
# 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.
|
# change them to suit your needs.
|
||||||
|
#
|
||||||
|
# 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
|
- name: community
|
||||||
path: ~/.dotfiles/cheat/community
|
path: COMMUNITY_PATH
|
||||||
tags: [ community ]
|
tags: [ community ]
|
||||||
readonly: true
|
readonly: true
|
||||||
|
|
||||||
# Maybe your company or department maintains a repository of cheatsheets as
|
|
||||||
# well. It's probably sensible to list those second.
|
|
||||||
- name: work
|
|
||||||
path: ~/.dotfiles/cheat/work
|
|
||||||
tags: [ work ]
|
|
||||||
readonly: false
|
|
||||||
|
|
||||||
# If you have personalized cheatsheets, list them last. They will take
|
# If you have personalized cheatsheets, list them last. They will take
|
||||||
# precedence over the more global cheatsheets.
|
# precedence over the more global cheatsheets.
|
||||||
- name: personal
|
- name: personal
|
||||||
path: ~/.dotfiles/cheat/personal
|
path: PERSONAL_PATH
|
||||||
tags: [ personal ]
|
tags: [ personal ]
|
||||||
readonly: false
|
readonly: false
|
||||||
|
|
||||||
|
# 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,
|
||||||
|
# directory-scoped cheatsheets will always be editable ('readonly: false').
|
||||||
|
221
doc/cheat.1
Normal file
221
doc/cheat.1
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
.\" Automatically generated by Pandoc 2.2.1
|
||||||
|
.\"
|
||||||
|
.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 \[en]init
|
||||||
|
Print a config file to stdout.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-c, \[en]colorize
|
||||||
|
Colorize output.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-d, \[en]directories
|
||||||
|
List cheatsheet directories.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-e, \[en]edit=\f[I]CHEATSHEET\f[]
|
||||||
|
Open \f[I]CHEATSHEET\f[] for editing.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-l, \[en]list
|
||||||
|
List available cheatsheets.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-p, \[en]path=\f[I]PATH\f[]
|
||||||
|
Filter only to sheets found on path \f[I]PATH\f[].
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-r, \[en]regex
|
||||||
|
Treat search \f[I]PHRASE\f[] as a regular expression.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-s, \[en]search=\f[I]PHRASE\f[]
|
||||||
|
Search cheatsheets for \f[I]PHRASE\f[].
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-t, \[en]tag=\f[I]TAG\f[]
|
||||||
|
Filter only to sheets tagged with \f[I]TAG\f[].
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-T, \[en]tags
|
||||||
|
List all tags in use.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \-v, \[en]version
|
||||||
|
Print the version number.
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B \[en]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 `work' 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 `apt':
|
||||||
|
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 `personal':
|
||||||
|
cheat \-l \-t \f[I]personal\f[]
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B To search for `ssh' 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]`(?:[0\-9]{1,3}.){3}[0\-9]{1,3}'\f[]
|
||||||
|
.RS
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B To remove (delete) the foo/bar cheatsheet:
|
||||||
|
cheat \[en]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'd like
|
||||||
|
to generate one automatically.
|
||||||
|
Alternatively, you may also generate a config file manually by running
|
||||||
|
\f[B]cheat \[en]init\f[] and saving its output to the appropriate
|
||||||
|
location for your platform.
|
||||||
|
.SS Cheatpaths
|
||||||
|
.PP
|
||||||
|
\f[B]cheat\f[] reads its cheatsheets from \[lq]cheatpaths\[rq], 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 RETURN VALUES
|
||||||
|
.IP "0." 3
|
||||||
|
Successful termination
|
||||||
|
.IP "1." 3
|
||||||
|
Application error
|
||||||
|
.IP "2." 3
|
||||||
|
Cheatsheet(s) not found
|
||||||
|
.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[]
|
192
doc/cheat.1.md
Normal file
192
doc/cheat.1.md
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
% 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**.
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
=============
|
||||||
|
|
||||||
|
0. Successful termination
|
||||||
|
|
||||||
|
1. Application error
|
||||||
|
|
||||||
|
2. Cheatsheet(s) not found
|
||||||
|
|
||||||
|
|
||||||
|
BUGS
|
||||||
|
====
|
||||||
|
|
||||||
|
See GitHub issues: <https://github.com/cheat/cheat/issues>
|
||||||
|
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
======
|
||||||
|
|
||||||
|
Christopher Allen Lane <chris@chris-allen-lane.com>
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
========
|
||||||
|
|
||||||
|
**fzf(1)**
|
||||||
|
|
18
go.mod
18
go.mod
@ -1,15 +1,19 @@
|
|||||||
module github.com/cheat/cheat
|
module github.com/cheat/cheat
|
||||||
|
|
||||||
go 1.13
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/chroma v0.6.7
|
github.com/alecthomas/chroma v0.8.1
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
|
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
||||||
github.com/mattn/go-isatty v0.0.10
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect
|
github.com/sergi/go-diff v1.1.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.4
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // 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.3.0
|
||||||
)
|
)
|
||||||
|
76
go.sum
76
go.sum
@ -1,66 +1,68 @@
|
|||||||
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
|
||||||
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
|
|
||||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||||
github.com/alecthomas/chroma v0.6.7 h1:1hKci+AyKOxJrugR9veaocu9DQGR2/GecI72BpaO0Rg=
|
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||||
github.com/alecthomas/chroma v0.6.7/go.mod h1:zVlgtbRS7BJDrDY9SB238RmpoCBCYFlLmcfZ3durxTk=
|
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||||
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
|
||||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
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/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
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 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
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=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
|
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||||
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
|
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||||
|
github.com/dlclark/regexp2 v1.4.0/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 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
|
||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||||
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
|
||||||
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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
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/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
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/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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1 h1:lA+aPRvltlx2fwv/BnxyYSDQo3pIeqzHgMO5GvK0T9E=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/tj/front v0.0.0-20170212063142-739be213b0a1/go.mod h1:deJrtusCTptAW4EUn5vBLpl3dhNqPqUwEjWJz5UNxpQ=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck=
|
||||||
|
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU=
|
||||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
@ -2,8 +2,8 @@ package cheatpath
|
|||||||
|
|
||||||
// Cheatpath encapsulates cheatsheet path information
|
// Cheatpath encapsulates cheatsheet path information
|
||||||
type Cheatpath struct {
|
type Cheatpath struct {
|
||||||
Name string `yaml:name`
|
Name string `yaml:"name"`
|
||||||
Path string `yaml:path`
|
Path string `yaml:"path"`
|
||||||
ReadOnly bool `yaml:readonly`
|
ReadOnly bool `yaml:"readonly"`
|
||||||
Tags []string `yaml:tags`
|
Tags []string `yaml:"tags"`
|
||||||
}
|
}
|
||||||
|
26
internal/config/color.go
Normal file
26
internal/config/color.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mattn/go-isatty"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Color indicates whether colorization should be applied to the output
|
||||||
|
func (c *Config) Color(opts map[string]interface{}) bool {
|
||||||
|
|
||||||
|
// default to the colorization specified in the configs...
|
||||||
|
colorize := c.Colorize
|
||||||
|
|
||||||
|
// ... however, only apply colorization if we're writing to a tty...
|
||||||
|
if !isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()) {
|
||||||
|
colorize = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... *unless* the --colorize flag was passed
|
||||||
|
if opts["--colorize"] == true {
|
||||||
|
colorize = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorize
|
||||||
|
}
|
22
internal/config/color_test.go
Normal file
22
internal/config/color_test.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestColor asserts that colorization rules are properly respected
|
||||||
|
func TestColor(t *testing.T) {
|
||||||
|
|
||||||
|
// mock a config
|
||||||
|
conf := Config{}
|
||||||
|
|
||||||
|
opts := map[string]interface{}{"--colorize": false}
|
||||||
|
if conf.Color(opts) {
|
||||||
|
t.Errorf("failed to respect --colorize (false)")
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = map[string]interface{}{"--colorize": true}
|
||||||
|
if !conf.Color(opts) {
|
||||||
|
t.Errorf("failed to respect --colorize (true)")
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
cp "github.com/cheat/cheat/internal/cheatpath"
|
cp "github.com/cheat/cheat/internal/cheatpath"
|
||||||
|
|
||||||
@ -13,15 +15,16 @@ import (
|
|||||||
|
|
||||||
// Config encapsulates configuration parameters
|
// Config encapsulates configuration parameters
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Colorize bool `yaml:colorize`
|
Colorize bool `yaml:"colorize"`
|
||||||
Editor string `yaml:editor`
|
Editor string `yaml:"editor"`
|
||||||
Cheatpaths []cp.Cheatpath `yaml:cheatpaths`
|
Cheatpaths []cp.Cheatpath `yaml:"cheatpaths"`
|
||||||
Style string `yaml:style`
|
Style string `yaml:"style"`
|
||||||
Formatter string `yaml:formatter`
|
Formatter string `yaml:"formatter"`
|
||||||
|
Pager string `yaml:"pager"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Config struct
|
// New returns a new Config struct
|
||||||
func New(opts map[string]interface{}, confPath string) (Config, error) {
|
func New(opts map[string]interface{}, confPath string, resolve bool) (Config, error) {
|
||||||
|
|
||||||
// read the config file
|
// read the config file
|
||||||
buf, err := ioutil.ReadFile(confPath)
|
buf, err := ioutil.ReadFile(confPath)
|
||||||
@ -38,14 +41,54 @@ func New(opts map[string]interface{}, confPath string) (Config, error) {
|
|||||||
return Config{}, fmt.Errorf("could not unmarshal yaml: %v", err)
|
return Config{}, fmt.Errorf("could not unmarshal yaml: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand ~ in config paths
|
// if a .cheat directory exists locally, append it to the cheatpaths
|
||||||
|
cwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, fmt.Errorf("failed to get cwd: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
local := filepath.Join(cwd, ".cheat")
|
||||||
|
if _, err := os.Stat(local); err == nil {
|
||||||
|
path := cp.Cheatpath{
|
||||||
|
Name: "cwd",
|
||||||
|
Path: local,
|
||||||
|
ReadOnly: false,
|
||||||
|
Tags: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Cheatpaths = append(conf.Cheatpaths, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// process cheatpaths
|
||||||
for i, cheatpath := range conf.Cheatpaths {
|
for i, cheatpath := range conf.Cheatpaths {
|
||||||
|
|
||||||
|
// expand ~ in config paths
|
||||||
expanded, err := homedir.Expand(cheatpath.Path)
|
expanded, err := homedir.Expand(cheatpath.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Config{}, fmt.Errorf("failed to expand ~: %v", err)
|
return Config{}, fmt.Errorf("failed to expand ~: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// follow symlinks
|
||||||
|
//
|
||||||
|
// NB: `resolve` is an ugly kludge that exists for the sake of unit-tests.
|
||||||
|
// It's necessary because `EvalSymlinks` will error if the symlink points
|
||||||
|
// to a non-existent location on the filesystem. When unit-testing,
|
||||||
|
// however, we don't want to have dependencies on the filesystem. As such,
|
||||||
|
// `resolve` is a switch that allows us to turn off symlink resolution when
|
||||||
|
// running the config tests.
|
||||||
|
if resolve {
|
||||||
|
evaled, err := filepath.EvalSymlinks(expanded)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, fmt.Errorf(
|
||||||
|
"failed to resolve symlink: %s: %v",
|
||||||
|
expanded,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded = evaled
|
||||||
|
}
|
||||||
|
|
||||||
conf.Cheatpaths[i].Path = expanded
|
conf.Cheatpaths[i].Path = expanded
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,5 +113,10 @@ func New(opts map[string]interface{}, confPath string) (Config, error) {
|
|||||||
conf.Formatter = "terminal16m"
|
conf.Formatter = "terminal16m"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a pager was not provided, set a default
|
||||||
|
if strings.TrimSpace(conf.Pager) == "" {
|
||||||
|
conf.Pager = ""
|
||||||
|
}
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
func TestConfigSuccessful(t *testing.T) {
|
func TestConfigSuccessful(t *testing.T) {
|
||||||
|
|
||||||
// initialize a config
|
// initialize a config
|
||||||
conf, err := New(map[string]interface{}{}, mock.Path("conf/conf.yml"))
|
conf, err := New(map[string]interface{}{}, mock.Path("conf/conf.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to parse config file: %v", err)
|
t.Errorf("failed to parse config file: %v", err)
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func TestConfigSuccessful(t *testing.T) {
|
|||||||
func TestConfigFailure(t *testing.T) {
|
func TestConfigFailure(t *testing.T) {
|
||||||
|
|
||||||
// attempt to read a non-existent config file
|
// attempt to read a non-existent config file
|
||||||
_, err := New(map[string]interface{}{}, "/does-not-exit")
|
_, err := New(map[string]interface{}{}, "/does-not-exit", false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("failed to error on unreadable config")
|
t.Errorf("failed to error on unreadable config")
|
||||||
}
|
}
|
||||||
@ -84,14 +84,14 @@ func TestEmptyEditor(t *testing.T) {
|
|||||||
os.Setenv("EDITOR", "")
|
os.Setenv("EDITOR", "")
|
||||||
|
|
||||||
// initialize a config
|
// initialize a config
|
||||||
conf, err := New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err := New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("failed to return an error on empty editor")
|
t.Errorf("failed to return an error on empty editor")
|
||||||
}
|
}
|
||||||
|
|
||||||
// set editor, and assert that it is respected
|
// set editor, and assert that it is respected
|
||||||
os.Setenv("EDITOR", "foo")
|
os.Setenv("EDITOR", "foo")
|
||||||
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to init configs: %v", err)
|
t.Errorf("failed to init configs: %v", err)
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ func TestEmptyEditor(t *testing.T) {
|
|||||||
|
|
||||||
// set visual, and assert that it overrides editor
|
// set visual, and assert that it overrides editor
|
||||||
os.Setenv("VISUAL", "bar")
|
os.Setenv("VISUAL", "bar")
|
||||||
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"))
|
conf, err = New(map[string]interface{}{}, mock.Path("conf/empty.yml"), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to init configs: %v", err)
|
t.Errorf("failed to init configs: %v", err)
|
||||||
}
|
}
|
||||||
|
24
internal/config/init.go
Normal file
24
internal/config/init.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init initializes a config file
|
||||||
|
func Init(confpath string, configs string) error {
|
||||||
|
|
||||||
|
// assert that the config directory exists
|
||||||
|
if err := os.MkdirAll(filepath.Dir(confpath), 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the config file
|
||||||
|
if err := ioutil.WriteFile(confpath, []byte(configs), 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to create file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
38
internal/config/init_test.go
Normal file
38
internal/config/init_test.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestInit asserts that configs are properly initialized
|
||||||
|
func TestInit(t *testing.T) {
|
||||||
|
|
||||||
|
// initialize a temporary config file
|
||||||
|
confFile, err := ioutil.TempFile("", "cheat-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up the temp file
|
||||||
|
defer os.Remove(confFile.Name())
|
||||||
|
|
||||||
|
// initialize the config file
|
||||||
|
conf := "mock config data"
|
||||||
|
if err = Init(confFile.Name(), conf); err != nil {
|
||||||
|
t.Errorf("failed to init config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read back the config file contents
|
||||||
|
bytes, err := ioutil.ReadFile(confFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to read config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that the contents were written correctly
|
||||||
|
got := string(bytes)
|
||||||
|
if got != conf {
|
||||||
|
t.Errorf("failed to write configs: want: %s, got: %s", conf, got)
|
||||||
|
}
|
||||||
|
}
|
@ -3,58 +3,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Path returns the config file path
|
// Path returns the config file path
|
||||||
func Path(sys string) (string, error) {
|
func Path(paths []string) (string, error) {
|
||||||
|
|
||||||
var paths []string
|
|
||||||
|
|
||||||
// if CHEAT_CONFIG_PATH is set, return it
|
|
||||||
if os.Getenv("CHEAT_CONFIG_PATH") != "" {
|
|
||||||
|
|
||||||
// expand ~
|
|
||||||
expanded, err := homedir.Expand(os.Getenv("CHEAT_CONFIG_PATH"))
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to expand ~: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return expanded, nil
|
|
||||||
|
|
||||||
// OSX config paths
|
|
||||||
} else if sys == "darwin" {
|
|
||||||
|
|
||||||
paths = []string{
|
|
||||||
path.Join(os.Getenv("XDG_CONFIG_HOME"), "/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".config/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".cheat/conf.yml"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linux config paths
|
|
||||||
} else if sys == "linux" {
|
|
||||||
|
|
||||||
paths = []string{
|
|
||||||
path.Join(os.Getenv("XDG_CONFIG_HOME"), "/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".config/cheat/conf.yml"),
|
|
||||||
path.Join(os.Getenv("HOME"), ".cheat/conf.yml"),
|
|
||||||
"/etc/cheat/conf.yml",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows config paths
|
|
||||||
} else if sys == "windows" {
|
|
||||||
|
|
||||||
paths = []string{
|
|
||||||
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("APPDATA")),
|
|
||||||
fmt.Sprintf("%s/cheat/conf.yml", os.Getenv("PROGRAMDATA")),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unsupported platforms
|
|
||||||
} else {
|
|
||||||
return "", fmt.Errorf("unsupported os: %s", sys)
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the config file exists on any paths
|
// check if the config file exists on any paths
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
|
53
internal/config/path_test.go
Normal file
53
internal/config/path_test.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestPathConfigNotExists asserts that `Path` identifies non-existent config
|
||||||
|
// files
|
||||||
|
func TestPathConfigNotExists(t *testing.T) {
|
||||||
|
|
||||||
|
// package (invalid) cheatpaths
|
||||||
|
paths := []string{"/cheat-test-conf-does-not-exist"}
|
||||||
|
|
||||||
|
// assert
|
||||||
|
if _, err := Path(paths); err == nil {
|
||||||
|
t.Errorf("failed to identify non-existent config file")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPathConfigExists asserts that `Path` identifies existent config files
|
||||||
|
func TestPathConfigExists(t *testing.T) {
|
||||||
|
|
||||||
|
// initialize a temporary config file
|
||||||
|
confFile, err := ioutil.TempFile("", "cheat-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up the temp file
|
||||||
|
defer os.Remove(confFile.Name())
|
||||||
|
|
||||||
|
// package cheatpaths
|
||||||
|
paths := []string{
|
||||||
|
"/cheat-test-conf-does-not-exist",
|
||||||
|
confFile.Name(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert
|
||||||
|
got, err := Path(paths)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to identify config file: %v", err)
|
||||||
|
}
|
||||||
|
if got != confFile.Name() {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return config path: want: %s, got: %s",
|
||||||
|
confFile.Name(),
|
||||||
|
got,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
54
internal/config/paths.go
Normal file
54
internal/config/paths.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Paths returns config file paths that are appropriate for the operating
|
||||||
|
// system
|
||||||
|
func Paths(
|
||||||
|
sys string,
|
||||||
|
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 {
|
||||||
|
|
||||||
|
// expand ~
|
||||||
|
expanded, err := homedir.Expand(confpath)
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, fmt.Errorf("failed to expand ~: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{expanded}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch sys {
|
||||||
|
case "darwin", "linux", "freebsd":
|
||||||
|
paths := []string{}
|
||||||
|
|
||||||
|
// don't include the `XDG_CONFIG_HOME` path if that envvar is not set
|
||||||
|
if xdgpath, ok := envvars["XDG_CONFIG_HOME"]; ok {
|
||||||
|
paths = append(paths, path.Join(xdgpath, "/cheat/conf.yml"))
|
||||||
|
}
|
||||||
|
|
||||||
|
paths = append(paths, []string{
|
||||||
|
path.Join(home, ".config/cheat/conf.yml"),
|
||||||
|
path.Join(home, ".cheat/conf.yml"),
|
||||||
|
"/etc/cheat/conf.yml",
|
||||||
|
}...)
|
||||||
|
|
||||||
|
return paths, nil
|
||||||
|
case "windows":
|
||||||
|
return []string{
|
||||||
|
path.Join(envvars["APPDATA"], "/cheat/conf.yml"),
|
||||||
|
path.Join(envvars["PROGRAMDATA"], "/cheat/conf.yml"),
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return []string{}, fmt.Errorf("unsupported os: %s", sys)
|
||||||
|
}
|
||||||
|
}
|
175
internal/config/paths_test.go
Normal file
175
internal/config/paths_test.go
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestValidatePathsNix asserts that the proper config paths are returned on
|
||||||
|
// *nix platforms
|
||||||
|
func TestValidatePathsNix(t *testing.T) {
|
||||||
|
|
||||||
|
// mock the user's home directory
|
||||||
|
home := "/home/foo"
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"XDG_CONFIG_HOME": "/home/bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the platforms to test
|
||||||
|
oses := []string{
|
||||||
|
"darwin",
|
||||||
|
"freebsd",
|
||||||
|
"linux",
|
||||||
|
}
|
||||||
|
|
||||||
|
// test each *nix os
|
||||||
|
for _, os := range oses {
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths(os, home, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/bar/cheat/conf.yml",
|
||||||
|
"/home/foo/.config/cheat/conf.yml",
|
||||||
|
"/home/foo/.cheat/conf.yml",
|
||||||
|
"/etc/cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsNixNoXDG asserts that the proper config paths are returned
|
||||||
|
// on *nix platforms when `XDG_CONFIG_HOME is not set
|
||||||
|
func TestValidatePathsNixNoXDG(t *testing.T) {
|
||||||
|
|
||||||
|
// mock the user's home directory
|
||||||
|
home := "/home/foo"
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{}
|
||||||
|
|
||||||
|
// specify the platforms to test
|
||||||
|
oses := []string{
|
||||||
|
"darwin",
|
||||||
|
"freebsd",
|
||||||
|
"linux",
|
||||||
|
}
|
||||||
|
|
||||||
|
// test each *nix os
|
||||||
|
for _, os := range oses {
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths(os, home, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/foo/.config/cheat/conf.yml",
|
||||||
|
"/home/foo/.cheat/conf.yml",
|
||||||
|
"/etc/cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsWindows asserts that the proper config paths are returned
|
||||||
|
// on Windows platforms
|
||||||
|
func TestValidatePathsWindows(t *testing.T) {
|
||||||
|
|
||||||
|
// mock the user's home directory
|
||||||
|
home := "not-used-on-windows"
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"APPDATA": "/apps",
|
||||||
|
"PROGRAMDATA": "/programs",
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths("windows", home, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/apps/cheat/conf.yml",
|
||||||
|
"/programs/cheat/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsUnsupported asserts that an error is returned on
|
||||||
|
// unsupported platforms
|
||||||
|
func TestValidatePathsUnsupported(t *testing.T) {
|
||||||
|
_, err := Paths("unsupported", "", map[string]string{})
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("failed to return error on unsupported platform")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestValidatePathsCheatConfigPath asserts that the proper config path is
|
||||||
|
// returned when `CHEAT_CONFIG_PATH` is explicitly specified.
|
||||||
|
func TestValidatePathsCheatConfigPath(t *testing.T) {
|
||||||
|
|
||||||
|
// mock the user's home directory
|
||||||
|
home := "/home/foo"
|
||||||
|
|
||||||
|
// mock some envvars
|
||||||
|
envvars := map[string]string{
|
||||||
|
"XDG_CONFIG_HOME": "/home/bar",
|
||||||
|
"CHEAT_CONFIG_PATH": "/home/baz/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the paths for the platform
|
||||||
|
paths, err := Paths("linux", home, envvars)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("paths returned an error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"/home/baz/conf.yml",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that output matches expectations
|
||||||
|
if !reflect.DeepEqual(paths, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return expected paths: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(paths),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
37
internal/display/display.go
Normal file
37
internal/display/display.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package display
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Display writes output either directly to stdout, or through a pager,
|
||||||
|
// depending upon configuration.
|
||||||
|
func Display(out string, conf config.Config) {
|
||||||
|
// if no pager was configured, print the output to stdout and exit
|
||||||
|
if conf.Pager == "" {
|
||||||
|
fmt.Print(out)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, pipe output through the pager
|
||||||
|
parts := strings.Split(conf.Pager, " ")
|
||||||
|
pager := parts[0]
|
||||||
|
args := parts[1:]
|
||||||
|
|
||||||
|
// run the pager
|
||||||
|
cmd := exec.Command(pager, args...)
|
||||||
|
cmd.Stdin = strings.NewReader(out)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
|
||||||
|
// handle errors
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, fmt.Sprintf("failed to write to pager: %v", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
44
internal/frontmatter/frontmatter.go
Normal file
44
internal/frontmatter/frontmatter.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package frontmatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Frontmatter encapsulates cheatsheet frontmatter data
|
||||||
|
type Frontmatter struct {
|
||||||
|
Tags []string
|
||||||
|
Syntax string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses cheatsheet frontmatter
|
||||||
|
func Parse(markdown string) (string, Frontmatter, error) {
|
||||||
|
|
||||||
|
// specify the frontmatter delimiter
|
||||||
|
delim := "---"
|
||||||
|
|
||||||
|
// initialize a frontmatter struct
|
||||||
|
var fm Frontmatter
|
||||||
|
|
||||||
|
// if the markdown does not contain frontmatter, pass it through unmodified
|
||||||
|
if !strings.HasPrefix(markdown, delim) {
|
||||||
|
return strings.TrimSpace(markdown), fm, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, split the frontmatter and cheatsheet text
|
||||||
|
parts := strings.SplitN(markdown, delim, 3)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
95
internal/frontmatter/frontmatter_test.go
Normal file
95
internal/frontmatter/frontmatter_test.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package frontmatter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestHasFrontmatter asserts that markdown is properly parsed when it contains
|
||||||
|
// frontmatter
|
||||||
|
func TestHasFrontmatter(t *testing.T) {
|
||||||
|
|
||||||
|
// stub our cheatsheet content
|
||||||
|
markdown := `---
|
||||||
|
syntax: go
|
||||||
|
tags: [ test ]
|
||||||
|
---
|
||||||
|
To foo the bar: baz`
|
||||||
|
|
||||||
|
// parse the frontmatter
|
||||||
|
text, fm, err := Parse(markdown)
|
||||||
|
|
||||||
|
// assert expectations
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to parse markdown: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "To foo the bar: baz"
|
||||||
|
if text != want {
|
||||||
|
t.Errorf("failed to parse text: want: %s, got: %s", want, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
want = "go"
|
||||||
|
if fm.Syntax != want {
|
||||||
|
t.Errorf("failed to parse syntax: want: %s, got: %s", want, fm.Syntax)
|
||||||
|
}
|
||||||
|
|
||||||
|
want = "test"
|
||||||
|
if fm.Tags[0] != want {
|
||||||
|
t.Errorf("failed to parse tags: want: %s, got: %s", want, fm.Tags[0])
|
||||||
|
}
|
||||||
|
if len(fm.Tags) != 1 {
|
||||||
|
t.Errorf("failed to parse tags: want: len 0, got: len %d", len(fm.Tags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHasFrontmatter asserts that markdown is properly parsed when it does not
|
||||||
|
// contain frontmatter
|
||||||
|
func TestHasNoFrontmatter(t *testing.T) {
|
||||||
|
|
||||||
|
// stub our cheatsheet content
|
||||||
|
markdown := "To foo the bar: baz"
|
||||||
|
|
||||||
|
// parse the frontmatter
|
||||||
|
text, fm, err := Parse(markdown)
|
||||||
|
|
||||||
|
// assert expectations
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("failed to parse markdown: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if text != markdown {
|
||||||
|
t.Errorf("failed to parse text: want: %s, got: %s", markdown, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fm.Syntax != "" {
|
||||||
|
t.Errorf("failed to parse syntax: want: '', got: %s", fm.Syntax)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fm.Tags) != 0 {
|
||||||
|
t.Errorf("failed to parse tags: want: len 0, got: len %d", len(fm.Tags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
24
internal/installer/clone.go
Normal file
24
internal/installer/clone.go
Normal 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
|
||||||
|
}
|
37
internal/installer/prompt.go
Normal file
37
internal/installer/prompt.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
37
internal/sheet/colorize.go
Normal file
37
internal/sheet/colorize.go
Normal 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()
|
||||||
|
}
|
34
internal/sheet/colorize_test.go
Normal file
34
internal/sheet/colorize_test.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package sheet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestColorize asserts that syntax-highlighting is correctly applied
|
||||||
|
func TestColorize(t *testing.T) {
|
||||||
|
|
||||||
|
// mock configs
|
||||||
|
conf := config.Config{
|
||||||
|
Formatter: "terminal16m",
|
||||||
|
Style: "solarized-dark",
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock a sheet
|
||||||
|
s := Sheet{
|
||||||
|
Text: "echo 'foo'",
|
||||||
|
}
|
||||||
|
|
||||||
|
// colorize the sheet text
|
||||||
|
s.Colorize(conf)
|
||||||
|
|
||||||
|
// initialize expectations
|
||||||
|
want := "[38;2;181;137;0mecho[0m[38;2;147;161;161m"
|
||||||
|
want += " [0m[38;2;42;161;152m'foo'[0m"
|
||||||
|
|
||||||
|
// assert
|
||||||
|
if s.Text != want {
|
||||||
|
t.Errorf("failed to colorize sheet: want: %s, got: %s", want, s.Text)
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +0,0 @@
|
|||||||
package sheet
|
|
||||||
|
|
||||||
// Match encapsulates search matches within cheatsheets
|
|
||||||
type Match struct {
|
|
||||||
Line int
|
|
||||||
Text string
|
|
||||||
}
|
|
@ -3,43 +3,22 @@ package sheet
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mgutz/ansi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Search searches for regexp matches in a cheatsheet's text, and optionally
|
// Search returns lines within a sheet's Text that match the search regex
|
||||||
// colorizes matching strings.
|
func (s *Sheet) Search(reg *regexp.Regexp) string {
|
||||||
func (s *Sheet) Search(reg *regexp.Regexp, colorize bool) []Match {
|
|
||||||
|
|
||||||
// record matches
|
// record matches
|
||||||
matches := []Match{}
|
matches := ""
|
||||||
|
|
||||||
// search through the cheatsheet's text line by line
|
// search through the cheatsheet's text line by line
|
||||||
// TODO: searching line-by-line is surely the "naive" approach. Revisit this
|
for _, line := range strings.Split(s.Text, "\n\n") {
|
||||||
// later with an eye for performance improvements.
|
|
||||||
for linenum, line := range strings.Split(s.Text, "\n") {
|
|
||||||
|
|
||||||
// exit early if the line doesn't match the regex
|
// exit early if the line doesn't match the regex
|
||||||
if !reg.MatchString(line) {
|
if reg.MatchString(line) {
|
||||||
continue
|
matches += line + "\n\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// init the match
|
return strings.TrimSpace(matches)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSearchNoMatch ensures that the expected output is returned when no
|
// TestSearchNoMatch ensures that the expected output is returned when no
|
||||||
@ -24,21 +22,21 @@ func TestSearchNoMatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search the sheet
|
// search the sheet
|
||||||
matches := sheet.Search(reg, false)
|
matches := sheet.Search(reg)
|
||||||
|
|
||||||
// assert that no matches were found
|
// assert that no matches were found
|
||||||
if len(matches) != 0 {
|
if matches != "" {
|
||||||
t.Errorf("failure: expected no matches: got: %s", spew.Sdump(matches))
|
t.Errorf("failure: expected no matches: got: %s", matches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSearchSingleMatchNoColor asserts that the expected output is returned
|
// TestSearchSingleMatch asserts that the expected output is returned
|
||||||
// when a single match is returned, and no colorization is applied.
|
// when a single match is returned
|
||||||
func TestSearchSingleMatchNoColor(t *testing.T) {
|
func TestSearchSingleMatch(t *testing.T) {
|
||||||
|
|
||||||
// mock a cheatsheet
|
// mock a cheatsheet
|
||||||
sheet := Sheet{
|
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
|
// compile the search regex
|
||||||
@ -48,69 +46,28 @@ func TestSearchSingleMatchNoColor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search the sheet
|
// search the sheet
|
||||||
matches := sheet.Search(reg, false)
|
matches := sheet.Search(reg)
|
||||||
|
|
||||||
// specify the expected results
|
// specify the expected results
|
||||||
want := []Match{
|
want := "The quick brown fox\njumped over"
|
||||||
Match{
|
|
||||||
Line: 1,
|
|
||||||
Text: "The quick brown fox",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert that the correct matches were returned
|
// assert that the correct matches were returned
|
||||||
if !reflect.DeepEqual(matches, want) {
|
if matches != want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed to return expected matches: want:\n%s, got:\n%s",
|
"failed to return expected matches: want:\n%s, got:\n%s",
|
||||||
spew.Sdump(want),
|
want,
|
||||||
spew.Sdump(matches),
|
matches,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestSearchSingleMatchColorized asserts that the expected output is returned
|
// TestSearchMultiMatch asserts that the expected output is returned
|
||||||
// when a single match is returned, and colorization is applied
|
// when a multiple matches are returned
|
||||||
func TestSearchSingleMatchColorized(t *testing.T) {
|
func TestSearchMultiMatch(t *testing.T) {
|
||||||
|
|
||||||
// mock a cheatsheet
|
// mock a cheatsheet
|
||||||
sheet := Sheet{
|
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
|
|
||||||
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.",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile the search regex
|
// compile the search regex
|
||||||
@ -120,66 +77,17 @@ func TestSearchMultiMatchNoColor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// search the sheet
|
// search the sheet
|
||||||
matches := sheet.Search(reg, false)
|
matches := sheet.Search(reg)
|
||||||
|
|
||||||
// specify the expected results
|
// specify the expected results
|
||||||
want := []Match{
|
want := "The quick brown fox\n\nthe lazy dog."
|
||||||
Match{
|
|
||||||
Line: 1,
|
|
||||||
Text: "The quick brown fox",
|
|
||||||
},
|
|
||||||
Match{
|
|
||||||
Line: 3,
|
|
||||||
Text: "the lazy dog.",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// assert that the correct matches were returned
|
// assert that the correct matches were returned
|
||||||
if !reflect.DeepEqual(matches, want) {
|
if !reflect.DeepEqual(matches, want) {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed to return expected matches: want:\n%s, got:\n%s",
|
"failed to return expected matches: want:\n%s, got:\n%s",
|
||||||
spew.Sdump(want),
|
want,
|
||||||
spew.Sdump(matches),
|
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),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/tj/front"
|
"github.com/cheat/cheat/internal/frontmatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// frontmatter is an un-exported helper struct used in parsing cheatsheets
|
|
||||||
type frontmatter struct {
|
|
||||||
Tags []string
|
|
||||||
Syntax string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sheet encapsulates sheet information
|
// Sheet encapsulates sheet information
|
||||||
type Sheet struct {
|
type Sheet struct {
|
||||||
Title string
|
Title string
|
||||||
@ -39,9 +32,8 @@ func New(
|
|||||||
return Sheet{}, fmt.Errorf("failed to read file: %s, %v", path, err)
|
return Sheet{}, fmt.Errorf("failed to read file: %s, %v", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the front-matter
|
// parse the cheatsheet frontmatter
|
||||||
var fm frontmatter
|
text, fm, err := frontmatter.Parse(string(markdown))
|
||||||
text, err := front.Unmarshal(markdown, &fm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Sheet{}, fmt.Errorf("failed to parse front-matter: %v", err)
|
return Sheet{}, fmt.Errorf("failed to parse front-matter: %v", err)
|
||||||
}
|
}
|
||||||
@ -56,7 +48,7 @@ func New(
|
|||||||
return Sheet{
|
return Sheet{
|
||||||
Title: title,
|
Title: title,
|
||||||
Path: path,
|
Path: path,
|
||||||
Text: strings.TrimSpace(string(text)) + "\n",
|
Text: text + "\n",
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
Syntax: fm.Syntax,
|
Syntax: fm.Syntax,
|
||||||
ReadOnly: readOnly,
|
ReadOnly: readOnly,
|
||||||
|
@ -69,3 +69,19 @@ func TestSheetFailure(t *testing.T) {
|
|||||||
t.Errorf("failed to return an error on unreadable sheet")
|
t.Errorf("failed to return an error on unreadable sheet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSheetFrontMatterFailure asserts that an error is returned if the sheet's
|
||||||
|
// frontmatter cannot be parsed.
|
||||||
|
func TestSheetFrontMatterFailure(t *testing.T) {
|
||||||
|
|
||||||
|
// initialize a sheet
|
||||||
|
_, err := New(
|
||||||
|
"foo",
|
||||||
|
mock.Path("sheet/bad-fm"),
|
||||||
|
[]string{"alpha", "bravo"},
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("failed to return an error on malformed front-matter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,7 +33,7 @@ func Load(cheatpaths []cp.Cheatpath) ([]map[string]sheet.Sheet, error) {
|
|||||||
|
|
||||||
// fail if an error occurred while walking the directory
|
// fail if an error occurred while walking the directory
|
||||||
if err != nil {
|
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
|
// don't register directories as cheatsheets
|
||||||
@ -45,18 +45,28 @@ func Load(cheatpaths []cp.Cheatpath) ([]map[string]sheet.Sheet, error) {
|
|||||||
// accessed. Eg: `cheat tar` - `tar` is the title)
|
// accessed. Eg: `cheat tar` - `tar` is the title)
|
||||||
title := strings.TrimPrefix(
|
title := strings.TrimPrefix(
|
||||||
strings.TrimPrefix(path, cheatpath.Path),
|
strings.TrimPrefix(path, cheatpath.Path),
|
||||||
"/",
|
string(os.PathSeparator),
|
||||||
)
|
)
|
||||||
|
|
||||||
// ignore dotfiles. Otherwise, we'll likely load .git/*
|
// ignore hidden files and directories. Otherwise, we'll likely load
|
||||||
if strings.HasPrefix(title, ".") {
|
// .git/* and .DS_Store.
|
||||||
|
//
|
||||||
|
// NB: this is still somewhat brittle in that it will miss files
|
||||||
|
// contained within hidden directories in the middle of a path, though
|
||||||
|
// that should not realistically occur.
|
||||||
|
if strings.HasPrefix(title, ".") || strings.HasPrefix(info.Name(), ".") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the cheatsheet file into a `sheet` struct
|
// parse the cheatsheet file into a `sheet` struct
|
||||||
s, err := sheet.New(title, path, cheatpath.Tags, cheatpath.ReadOnly)
|
s, err := sheet.New(title, path, cheatpath.Tags, cheatpath.ReadOnly)
|
||||||
if err != nil {
|
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
|
// register the cheatsheet on its cheatpath, keyed by its title
|
||||||
|
36
internal/sheets/tags.go
Normal file
36
internal/sheets/tags.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package sheets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/sheet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tags returns a slice of all tags in use in any sheet
|
||||||
|
func Tags(cheatpaths []map[string]sheet.Sheet) []string {
|
||||||
|
|
||||||
|
// create a map of all tags in use in any sheet
|
||||||
|
tags := make(map[string]bool)
|
||||||
|
|
||||||
|
// iterate over all tags on all sheets on all cheatpaths
|
||||||
|
for _, path := range cheatpaths {
|
||||||
|
for _, sheet := range path {
|
||||||
|
for _, tag := range sheet.Tags {
|
||||||
|
tags[tag] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// restructure the map into a slice
|
||||||
|
sorted := []string{}
|
||||||
|
for tag := range tags {
|
||||||
|
sorted = append(sorted, tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the slice
|
||||||
|
sort.Slice(sorted, func(i, j int) bool {
|
||||||
|
return sorted[i] < sorted[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
return sorted
|
||||||
|
}
|
51
internal/sheets/tags_test.go
Normal file
51
internal/sheets/tags_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package sheets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
|
"github.com/cheat/cheat/internal/sheet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestTags asserts that cheatsheet tags are properly returned
|
||||||
|
func TestTags(t *testing.T) {
|
||||||
|
|
||||||
|
// mock cheatsheets available on multiple cheatpaths
|
||||||
|
cheatpaths := []map[string]sheet.Sheet{
|
||||||
|
|
||||||
|
// mock community cheatsheets
|
||||||
|
map[string]sheet.Sheet{
|
||||||
|
"foo": sheet.Sheet{Title: "foo", Tags: []string{"alpha"}},
|
||||||
|
"bar": sheet.Sheet{Title: "bar", Tags: []string{"alpha", "bravo"}},
|
||||||
|
},
|
||||||
|
|
||||||
|
// mock local cheatsheets
|
||||||
|
map[string]sheet.Sheet{
|
||||||
|
"bar": sheet.Sheet{Title: "bar", Tags: []string{"bravo", "charlie"}},
|
||||||
|
"baz": sheet.Sheet{Title: "baz", Tags: []string{"delta"}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// consolidate the cheatsheets
|
||||||
|
tags := Tags(cheatpaths)
|
||||||
|
|
||||||
|
// specify the expected output
|
||||||
|
want := []string{
|
||||||
|
"alpha",
|
||||||
|
"bravo",
|
||||||
|
"charlie",
|
||||||
|
"delta",
|
||||||
|
}
|
||||||
|
|
||||||
|
// assert that the cheatsheets properly consolidated
|
||||||
|
if !reflect.DeepEqual(tags, want) {
|
||||||
|
t.Errorf(
|
||||||
|
"failed to return tags: want:\n%s, got:\n%s",
|
||||||
|
spew.Sdump(want),
|
||||||
|
spew.Sdump(tags),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
4
mocks/sheet/bad-fm
Normal file
4
mocks/sheet/bad-fm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
syntax: sh
|
||||||
|
|
||||||
|
This is malformed frontmatter.
|
74
scripts/cheat.bash
Executable file
74
scripts/cheat.bash
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
# cheat(1) completion -*- shell-script -*-
|
||||||
|
|
||||||
|
# generate cheatsheet completions, optionally using `fzf`
|
||||||
|
_cheat_complete_cheatsheets()
|
||||||
|
{
|
||||||
|
if [[ "$CHEAT_USE_FZF" = true ]]; then
|
||||||
|
FZF_COMPLETION_TRIGGER='' _fzf_complete "--no-multi" "$@" < <(
|
||||||
|
cheat -l | tail -n +2 | cut -d' ' -f1
|
||||||
|
)
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -l | tail -n +2 | cut -d' ' -f1)" -- "$cur") )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# generate tag completions, optionally using `fzf`
|
||||||
|
_cheat_complete_tags()
|
||||||
|
{
|
||||||
|
if [ "$CHEAT_USE_FZF" = true ]; then
|
||||||
|
FZF_COMPLETION_TRIGGER='' _fzf_complete "--no-multi" "$@" < <(cheat -T)
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -T)" -- "$cur") )
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# implement the `cheat` autocompletions
|
||||||
|
_cheat()
|
||||||
|
{
|
||||||
|
local cur prev words cword split
|
||||||
|
_init_completion -s || return
|
||||||
|
|
||||||
|
# complete options that are currently being typed: `--col` => `--colorize`
|
||||||
|
if [[ $cur == -* ]]; then
|
||||||
|
COMPREPLY=( $(compgen -W '$(_parse_help "$1" | sed "s/=//g")' -- "$cur") )
|
||||||
|
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# implement completions
|
||||||
|
case $prev in
|
||||||
|
--colorize|-c|\
|
||||||
|
--directories|-d|\
|
||||||
|
--init|\
|
||||||
|
--regex|-r|\
|
||||||
|
--search|-s|\
|
||||||
|
--tags|-T|\
|
||||||
|
--version|-v)
|
||||||
|
# noop the above, which should implement no completions
|
||||||
|
;;
|
||||||
|
--edit|-e)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--list|-l)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--path|-p)
|
||||||
|
COMPREPLY=( $(compgen -W "$(cheat -d | cut -d':' -f1)" -- "$cur") )
|
||||||
|
;;
|
||||||
|
--rm)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
--tag|-t)
|
||||||
|
_cheat_complete_tags
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_cheat_complete_cheatsheets
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$split && return
|
||||||
|
|
||||||
|
} &&
|
||||||
|
complete -F _cheat cheat
|
||||||
|
|
||||||
|
# ex: filetype=sh
|
13
scripts/cheat.fish
Executable file
13
scripts/cheat.fish
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
complete -c cheat -f -a "(cheat -l | tail -n +2 | cut -d ' ' -f 1)"
|
||||||
|
complete -c cheat -l init -d "Write a default config file to stdout"
|
||||||
|
complete -c cheat -s c -l colorize -d "Colorize output"
|
||||||
|
complete -c cheat -s d -l directories -d "List cheatsheet directories"
|
||||||
|
complete -c cheat -s e -l edit -x -a "(cheat -l | tail -n +2 | cut -d ' ' -f 1)" -d "Edit cheatsheet"
|
||||||
|
complete -c cheat -s l -l list -d "List cheatsheets"
|
||||||
|
complete -c cheat -s p -l path -x -a "(cheat -d | cut -d ':' -f 1)" -d "Return only sheets found on given path"
|
||||||
|
complete -c cheat -s r -l regex -d "Treat search phrase as a regex"
|
||||||
|
complete -c cheat -s s -l search -x -d "Search cheatsheets for given phrase"
|
||||||
|
complete -c cheat -s t -l tag -x -a "(cheat -T)" -d "Return only sheets matching the given tag"
|
||||||
|
complete -c cheat -s T -l tags -d "List all tags in use"
|
||||||
|
complete -c cheat -s v -l version -d "Print the version number"
|
||||||
|
complete -c cheat -l rm -x -a "(cheat -l | tail -n +2 | cut -d ' ' -f 1)" -d "Remove (delete) cheatsheet"
|
66
scripts/cheat.zsh
Executable file
66
scripts/cheat.zsh
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#compdef cheat
|
||||||
|
|
||||||
|
local cheats taglist pathlist
|
||||||
|
|
||||||
|
_cheat_complete_personal_cheatsheets()
|
||||||
|
{
|
||||||
|
cheats=("${(f)$(cheat -l -t personal | tail -n +2 | cut -d' ' -f1)}")
|
||||||
|
_describe -t cheats 'cheats' cheats
|
||||||
|
}
|
||||||
|
|
||||||
|
_cheat_complete_full_cheatsheets()
|
||||||
|
{
|
||||||
|
cheats=("${(f)$(cheat -l | 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>]: :->personal' \
|
||||||
|
'(-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>]: :->personal' \
|
||||||
|
'(-)*: :->full'
|
||||||
|
|
||||||
|
case $state in
|
||||||
|
(none)
|
||||||
|
;;
|
||||||
|
(full)
|
||||||
|
_cheat_complete_full_cheatsheets
|
||||||
|
;;
|
||||||
|
(personal)
|
||||||
|
_cheat_complete_personal_cheatsheets
|
||||||
|
;;
|
||||||
|
(taglist)
|
||||||
|
_cheat_complete_tags
|
||||||
|
;;
|
||||||
|
(pathlist)
|
||||||
|
_cheat_complete_paths
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
_cheat
|
@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This function enables you to choose a cheatsheet to view by selecting output
|
|
||||||
# from `cheat -l`. `source` it in your shell to enable it. (Consider renaming
|
|
||||||
# or aliasing it to something convenient.)
|
|
||||||
|
|
||||||
# Arguments passed to this function (like --color) will be passed to the second
|
|
||||||
# invokation of `cheat`.
|
|
||||||
function cheat-fzf {
|
|
||||||
eval `cheat -l | tail -n +2 | fzf | awk -v vars="$*" '{ print "cheat " $1 " -t " $3, vars }'`
|
|
||||||
}
|
|
15
vendor/github.com/alecthomas/chroma/.golangci.yml
generated
vendored
15
vendor/github.com/alecthomas/chroma/.golangci.yml
generated
vendored
@ -15,6 +15,16 @@ linters:
|
|||||||
- gocyclo
|
- gocyclo
|
||||||
- dupl
|
- dupl
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
|
- funlen
|
||||||
|
- godox
|
||||||
|
- wsl
|
||||||
|
- gomnd
|
||||||
|
- gocognit
|
||||||
|
- goerr113
|
||||||
|
- nolintlint
|
||||||
|
- testpackage
|
||||||
|
- godot
|
||||||
|
- nestif
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
govet:
|
govet:
|
||||||
@ -43,3 +53,8 @@ issues:
|
|||||||
- 'Potential file inclusion via variable'
|
- 'Potential file inclusion via variable'
|
||||||
- 'should have comment or be unexported'
|
- 'should have comment or be unexported'
|
||||||
- 'comment on exported var .* should be of the form'
|
- 'comment on exported var .* should be of the form'
|
||||||
|
- 'at least one file in a package should have a package comment'
|
||||||
|
- 'string literal contains the Unicode'
|
||||||
|
- 'methods on the same type should have the same receiver name'
|
||||||
|
- '_TokenType_name should be _TokenTypeName'
|
||||||
|
- '`_TokenType_map` should be `_TokenTypeMap`'
|
||||||
|
6
vendor/github.com/alecthomas/chroma/.goreleaser.yml
generated
vendored
6
vendor/github.com/alecthomas/chroma/.goreleaser.yml
generated
vendored
@ -3,7 +3,8 @@ release:
|
|||||||
github:
|
github:
|
||||||
owner: alecthomas
|
owner: alecthomas
|
||||||
name: chroma
|
name: chroma
|
||||||
brew:
|
brews:
|
||||||
|
-
|
||||||
install: bin.install "chroma"
|
install: bin.install "chroma"
|
||||||
builds:
|
builds:
|
||||||
- goos:
|
- goos:
|
||||||
@ -18,7 +19,8 @@ builds:
|
|||||||
main: ./cmd/chroma/main.go
|
main: ./cmd/chroma/main.go
|
||||||
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
|
ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
|
||||||
binary: chroma
|
binary: chroma
|
||||||
archive:
|
archives:
|
||||||
|
-
|
||||||
format: tar.gz
|
format: tar.gz
|
||||||
name_template: '{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{
|
name_template: '{{ .Binary }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{
|
||||||
.Arm }}{{ end }}'
|
.Arm }}{{ end }}'
|
||||||
|
4
vendor/github.com/alecthomas/chroma/.travis.yml
generated
vendored
4
vendor/github.com/alecthomas/chroma/.travis.yml
generated
vendored
@ -1,8 +1,10 @@
|
|||||||
sudo: false
|
sudo: false
|
||||||
language: go
|
language: go
|
||||||
|
go:
|
||||||
|
- "1.13.x"
|
||||||
script:
|
script:
|
||||||
- go test -v ./...
|
- go test -v ./...
|
||||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.15.0
|
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.26.0
|
||||||
- ./bin/golangci-lint run
|
- ./bin/golangci-lint run
|
||||||
- git clean -fdx .
|
- git clean -fdx .
|
||||||
after_success:
|
after_success:
|
||||||
|
19
vendor/github.com/alecthomas/chroma/Makefile
generated
vendored
Normal file
19
vendor/github.com/alecthomas/chroma/Makefile
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.PHONY: chromad upload all
|
||||||
|
|
||||||
|
all: README.md tokentype_string.go
|
||||||
|
|
||||||
|
README.md: lexers/*/*.go
|
||||||
|
./table.py
|
||||||
|
|
||||||
|
tokentype_string.go: types.go
|
||||||
|
go generate
|
||||||
|
|
||||||
|
chromad:
|
||||||
|
(cd ./cmd/chromad && go get github.com/GeertJohan/go.rice/rice@master && go install github.com/GeertJohan/go.rice/rice)
|
||||||
|
rm -f chromad
|
||||||
|
(export CGOENABLED=0 GOOS=linux ; cd ./cmd/chromad && go build -o ../../chromad .)
|
||||||
|
rice append -i ./cmd/chromad --exec=./chromad
|
||||||
|
|
||||||
|
upload: chromad
|
||||||
|
scp chromad root@swapoff.org: && \
|
||||||
|
ssh root@swapoff.org 'install -m755 ./chromad /srv/http/swapoff.org/bin && service chromad restart'
|
9
vendor/github.com/alecthomas/chroma/README.md
generated
vendored
9
vendor/github.com/alecthomas/chroma/README.md
generated
vendored
@ -44,17 +44,17 @@ F | Factor, Fish, Forth, Fortran, FSharp
|
|||||||
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
|
G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
|
||||||
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
|
H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
|
||||||
I | Idris, INI, Io
|
I | Idris, INI, Io
|
||||||
J | Java, JavaScript, JSON, Julia, Jungle
|
J | J, Java, JavaScript, JSON, Julia, Jungle
|
||||||
K | Kotlin
|
K | Kotlin
|
||||||
L | Lighttpd configuration file, LLVM, Lua
|
L | Lighttpd configuration file, LLVM, Lua
|
||||||
M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
|
M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, MLIR, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
|
||||||
N | NASM, Newspeak, Nginx configuration file, Nim, Nix
|
N | NASM, Newspeak, Nginx configuration file, Nim, Nix
|
||||||
O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
|
O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
|
||||||
P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
|
P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
|
||||||
Q | QBasic
|
Q | QBasic
|
||||||
R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
|
R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
|
||||||
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
|
S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, SML, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
|
||||||
T | TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
|
T | TableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
|
||||||
V | VB.net, verilog, VHDL, VimL, vue
|
V | VB.net, verilog, VHDL, VimL, vue
|
||||||
W | WDTE
|
W | WDTE
|
||||||
X | XML, Xorg
|
X | XML, Xorg
|
||||||
@ -183,6 +183,7 @@ following constructor options:
|
|||||||
- `ClassPrefix(prefix)` - prefix each generated CSS class.
|
- `ClassPrefix(prefix)` - prefix each generated CSS class.
|
||||||
- `TabWidth(width)` - Set the rendered tab width, in characters.
|
- `TabWidth(width)` - Set the rendered tab width, in characters.
|
||||||
- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`).
|
- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`).
|
||||||
|
- `LinkableLineNumbers()` - Make the line numbers linkable.
|
||||||
- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`).
|
- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`).
|
||||||
- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans.
|
- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans.
|
||||||
|
|
||||||
|
2
vendor/github.com/alecthomas/chroma/delegate.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/delegate.go
generated
vendored
@ -34,7 +34,7 @@ type insertion struct {
|
|||||||
tokens []Token
|
tokens []Token
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
|
func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
|
||||||
tokens, err := Tokenise(Coalesce(d.language), options, text)
|
tokens, err := Tokenise(Coalesce(d.language), options, text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
4
vendor/github.com/alecthomas/chroma/formatters/api.go
generated
vendored
4
vendor/github.com/alecthomas/chroma/formatters/api.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alecthomas/chroma"
|
"github.com/alecthomas/chroma"
|
||||||
"github.com/alecthomas/chroma/formatters/html"
|
"github.com/alecthomas/chroma/formatters/html"
|
||||||
|
"github.com/alecthomas/chroma/formatters/svg"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -19,7 +20,8 @@ var (
|
|||||||
return nil
|
return nil
|
||||||
}))
|
}))
|
||||||
// Default HTML formatter outputs self-contained HTML.
|
// Default HTML formatter outputs self-contained HTML.
|
||||||
htmlFull = Register("html", html.New(html.Standalone(), html.WithClasses())) // nolint
|
htmlFull = Register("html", html.New(html.Standalone(true), html.WithClasses(true))) // nolint
|
||||||
|
SVG = Register("svg", svg.New(svg.EmbedFont("Liberation Mono", svg.FontLiberationMono, svg.WOFF)))
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fallback formatter.
|
// Fallback formatter.
|
||||||
|
139
vendor/github.com/alecthomas/chroma/formatters/html/html.go
generated
vendored
139
vendor/github.com/alecthomas/chroma/formatters/html/html.go
generated
vendored
@ -14,32 +14,59 @@ import (
|
|||||||
type Option func(f *Formatter)
|
type Option func(f *Formatter)
|
||||||
|
|
||||||
// Standalone configures the HTML formatter for generating a standalone HTML document.
|
// Standalone configures the HTML formatter for generating a standalone HTML document.
|
||||||
func Standalone() Option { return func(f *Formatter) { f.standalone = true } }
|
func Standalone(b bool) Option { return func(f *Formatter) { f.standalone = b } }
|
||||||
|
|
||||||
// ClassPrefix sets the CSS class prefix.
|
// ClassPrefix sets the CSS class prefix.
|
||||||
func ClassPrefix(prefix string) Option { return func(f *Formatter) { f.prefix = prefix } }
|
func ClassPrefix(prefix string) Option { return func(f *Formatter) { f.prefix = prefix } }
|
||||||
|
|
||||||
// WithClasses emits HTML using CSS classes, rather than inline styles.
|
// WithClasses emits HTML using CSS classes, rather than inline styles.
|
||||||
func WithClasses() Option { return func(f *Formatter) { f.Classes = true } }
|
func WithClasses(b bool) Option { return func(f *Formatter) { f.Classes = b } }
|
||||||
|
|
||||||
|
// WithAllClasses disables an optimisation that omits redundant CSS classes.
|
||||||
|
func WithAllClasses(b bool) Option { return func(f *Formatter) { f.allClasses = b } }
|
||||||
|
|
||||||
// TabWidth sets the number of characters for a tab. Defaults to 8.
|
// TabWidth sets the number of characters for a tab. Defaults to 8.
|
||||||
func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } }
|
func TabWidth(width int) Option { return func(f *Formatter) { f.tabWidth = width } }
|
||||||
|
|
||||||
// PreventSurroundingPre prevents the surrounding pre tags around the generated code
|
// PreventSurroundingPre prevents the surrounding pre tags around the generated code.
|
||||||
func PreventSurroundingPre() Option { return func(f *Formatter) { f.preventSurroundingPre = true } }
|
func PreventSurroundingPre(b bool) Option {
|
||||||
|
return func(f *Formatter) {
|
||||||
|
if b {
|
||||||
|
f.preWrapper = nopPreWrapper
|
||||||
|
} else {
|
||||||
|
f.preWrapper = defaultPreWrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPreWrapper allows control of the surrounding pre tags.
|
||||||
|
func WithPreWrapper(wrapper PreWrapper) Option {
|
||||||
|
return func(f *Formatter) {
|
||||||
|
f.preWrapper = wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithLineNumbers formats output with line numbers.
|
// WithLineNumbers formats output with line numbers.
|
||||||
func WithLineNumbers() Option {
|
func WithLineNumbers(b bool) Option {
|
||||||
return func(f *Formatter) {
|
return func(f *Formatter) {
|
||||||
f.lineNumbers = true
|
f.lineNumbers = b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LineNumbersInTable will, when combined with WithLineNumbers, separate the line numbers
|
// LineNumbersInTable will, when combined with WithLineNumbers, separate the line numbers
|
||||||
// and code in table td's, which make them copy-and-paste friendly.
|
// and code in table td's, which make them copy-and-paste friendly.
|
||||||
func LineNumbersInTable() Option {
|
func LineNumbersInTable(b bool) Option {
|
||||||
return func(f *Formatter) {
|
return func(f *Formatter) {
|
||||||
f.lineNumbersInTable = true
|
f.lineNumbersInTable = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkableLineNumbers decorates the line numbers HTML elements with an "id"
|
||||||
|
// attribute so they can be linked.
|
||||||
|
func LinkableLineNumbers(b bool, prefix string) Option {
|
||||||
|
return func(f *Formatter) {
|
||||||
|
f.linkableLineNumbers = b
|
||||||
|
f.lineNumbersIDPrefix = prefix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +91,7 @@ func BaseLineNumber(n int) Option {
|
|||||||
func New(options ...Option) *Formatter {
|
func New(options ...Option) *Formatter {
|
||||||
f := &Formatter{
|
f := &Formatter{
|
||||||
baseLineNumber: 1,
|
baseLineNumber: 1,
|
||||||
|
preWrapper: defaultPreWrapper,
|
||||||
}
|
}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(f)
|
option(f)
|
||||||
@ -71,15 +99,58 @@ func New(options ...Option) *Formatter {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreWrapper defines the operations supported in WithPreWrapper.
|
||||||
|
type PreWrapper interface {
|
||||||
|
// Start is called to write a start <pre> element.
|
||||||
|
// The code flag tells whether this block surrounds
|
||||||
|
// highlighted code. This will be false when surrounding
|
||||||
|
// line numbers.
|
||||||
|
Start(code bool, styleAttr string) string
|
||||||
|
|
||||||
|
// End is called to write the end </pre> element.
|
||||||
|
End(code bool) string
|
||||||
|
}
|
||||||
|
|
||||||
|
type preWrapper struct {
|
||||||
|
start func(code bool, styleAttr string) string
|
||||||
|
end func(code bool) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p preWrapper) Start(code bool, styleAttr string) string {
|
||||||
|
return p.start(code, styleAttr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p preWrapper) End(code bool) string {
|
||||||
|
return p.end(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
nopPreWrapper = preWrapper{
|
||||||
|
start: func(code bool, styleAttr string) string { return "" },
|
||||||
|
end: func(code bool) string { return "" },
|
||||||
|
}
|
||||||
|
defaultPreWrapper = preWrapper{
|
||||||
|
start: func(code bool, styleAttr string) string {
|
||||||
|
return fmt.Sprintf("<pre%s>", styleAttr)
|
||||||
|
},
|
||||||
|
end: func(code bool) string {
|
||||||
|
return "</pre>"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Formatter that generates HTML.
|
// Formatter that generates HTML.
|
||||||
type Formatter struct {
|
type Formatter struct {
|
||||||
standalone bool
|
standalone bool
|
||||||
prefix string
|
prefix string
|
||||||
Classes bool // Exported field to detect when classes are being used
|
Classes bool // Exported field to detect when classes are being used
|
||||||
preventSurroundingPre bool
|
allClasses bool
|
||||||
|
preWrapper PreWrapper
|
||||||
tabWidth int
|
tabWidth int
|
||||||
lineNumbers bool
|
lineNumbers bool
|
||||||
lineNumbersInTable bool
|
lineNumbersInTable bool
|
||||||
|
linkableLineNumbers bool
|
||||||
|
lineNumbersIDPrefix string
|
||||||
highlightRanges highlightRanges
|
highlightRanges highlightRanges
|
||||||
baseLineNumber int
|
baseLineNumber int
|
||||||
}
|
}
|
||||||
@ -91,11 +162,6 @@ func (h highlightRanges) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
|||||||
func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] }
|
func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] }
|
||||||
|
|
||||||
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
||||||
defer func() {
|
|
||||||
if perr := recover(); perr != nil {
|
|
||||||
err = perr.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return f.writeHTML(w, style, iterator.Tokens())
|
return f.writeHTML(w, style, iterator.Tokens())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +192,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
wrapInTable := f.lineNumbers && f.lineNumbersInTable
|
wrapInTable := f.lineNumbers && f.lineNumbersInTable
|
||||||
|
|
||||||
lines := chroma.SplitTokensIntoLines(tokens)
|
lines := chroma.SplitTokensIntoLines(tokens)
|
||||||
lineDigits := len(fmt.Sprintf("%d", len(lines)))
|
lineDigits := len(fmt.Sprintf("%d", f.baseLineNumber+len(lines)-1))
|
||||||
highlightIndex := 0
|
highlightIndex := 0
|
||||||
|
|
||||||
if wrapInTable {
|
if wrapInTable {
|
||||||
@ -134,9 +200,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.Background))
|
fmt.Fprintf(w, "<div%s>\n", f.styleAttr(css, chroma.Background))
|
||||||
fmt.Fprintf(w, "<table%s><tr>", f.styleAttr(css, chroma.LineTable))
|
fmt.Fprintf(w, "<table%s><tr>", f.styleAttr(css, chroma.LineTable))
|
||||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
|
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD))
|
||||||
if !f.preventSurroundingPre {
|
fmt.Fprintf(w, f.preWrapper.Start(false, f.styleAttr(css, chroma.Background)))
|
||||||
fmt.Fprintf(w, "<pre%s>", f.styleAttr(css, chroma.Background))
|
|
||||||
}
|
|
||||||
for index := range lines {
|
for index := range lines {
|
||||||
line := f.baseLineNumber + index
|
line := f.baseLineNumber + index
|
||||||
highlight, next := f.shouldHighlight(highlightIndex, line)
|
highlight, next := f.shouldHighlight(highlightIndex, line)
|
||||||
@ -147,22 +211,19 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
fmt.Fprintf(w, "<span%s>", f.styleAttr(css, chroma.LineHighlight))
|
fmt.Fprintf(w, "<span%s>", f.styleAttr(css, chroma.LineHighlight))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, "<span%s>%*d\n</span>", f.styleAttr(css, chroma.LineNumbersTable), lineDigits, line)
|
fmt.Fprintf(w, "<span%s%s>%*d\n</span>", f.styleAttr(css, chroma.LineNumbersTable), f.lineIDAttribute(line), lineDigits, line)
|
||||||
|
|
||||||
if highlight {
|
if highlight {
|
||||||
fmt.Fprintf(w, "</span>")
|
fmt.Fprintf(w, "</span>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !f.preventSurroundingPre {
|
fmt.Fprint(w, f.preWrapper.End(false))
|
||||||
fmt.Fprint(w, "</pre>")
|
|
||||||
}
|
|
||||||
fmt.Fprint(w, "</td>\n")
|
fmt.Fprint(w, "</td>\n")
|
||||||
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
|
fmt.Fprintf(w, "<td%s>\n", f.styleAttr(css, chroma.LineTableTD, "width:100%"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.preventSurroundingPre {
|
fmt.Fprintf(w, f.preWrapper.Start(true, f.styleAttr(css, chroma.Background)))
|
||||||
fmt.Fprintf(w, "<pre%s>", f.styleAttr(css, chroma.Background))
|
|
||||||
}
|
|
||||||
highlightIndex = 0
|
highlightIndex = 0
|
||||||
for index, tokens := range lines {
|
for index, tokens := range lines {
|
||||||
// 1-based line number.
|
// 1-based line number.
|
||||||
@ -176,7 +237,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if f.lineNumbers && !wrapInTable {
|
if f.lineNumbers && !wrapInTable {
|
||||||
fmt.Fprintf(w, "<span%s>%*d</span>", f.styleAttr(css, chroma.LineNumbers), lineDigits, line)
|
fmt.Fprintf(w, "<span%s%s>%*d</span>", f.styleAttr(css, chroma.LineNumbers), f.lineIDAttribute(line), lineDigits, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
@ -192,9 +253,7 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.preventSurroundingPre {
|
fmt.Fprintf(w, f.preWrapper.End(true))
|
||||||
fmt.Fprint(w, "</pre>")
|
|
||||||
}
|
|
||||||
|
|
||||||
if wrapInTable {
|
if wrapInTable {
|
||||||
fmt.Fprint(w, "</td></tr></table>\n")
|
fmt.Fprint(w, "</td></tr></table>\n")
|
||||||
@ -209,6 +268,13 @@ func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) lineIDAttribute(line int) string {
|
||||||
|
if !f.linkableLineNumbers {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(" id=\"%s%d\"", f.lineNumbersIDPrefix, line)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) {
|
func (f *Formatter) shouldHighlight(highlightIndex, line int) (bool, bool) {
|
||||||
next := false
|
next := false
|
||||||
for highlightIndex < len(f.highlightRanges) && line > f.highlightRanges[highlightIndex][1] {
|
for highlightIndex < len(f.highlightRanges) && line > f.highlightRanges[highlightIndex][1] {
|
||||||
@ -283,6 +349,13 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Special-case line number highlighting when targeted.
|
||||||
|
if f.lineNumbers || f.lineNumbersInTable {
|
||||||
|
targetedLineCSS := StyleEntryToCSS(style.Get(chroma.LineHighlight))
|
||||||
|
for _, tt := range []chroma.TokenType{chroma.LineNumbers, chroma.LineNumbersTable} {
|
||||||
|
fmt.Fprintf(w, "/* %s targeted by URL anchor */ .%schroma .%s:target { %s }\n", tt, f.prefix, f.class(tt), targetedLineCSS)
|
||||||
|
}
|
||||||
|
}
|
||||||
tts := []int{}
|
tts := []int{}
|
||||||
for tt := range css {
|
for tt := range css {
|
||||||
tts = append(tts, int(tt))
|
tts = append(tts, int(tt))
|
||||||
@ -293,8 +366,12 @@ func (f *Formatter) WriteCSS(w io.Writer, style *chroma.Style) error {
|
|||||||
if tt == chroma.Background {
|
if tt == chroma.Background {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
class := f.class(tt)
|
||||||
|
if class == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
styles := css[tt]
|
styles := css[tt]
|
||||||
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s { %s }\n", tt, f.prefix, f.class(tt), styles); err != nil {
|
if _, err := fmt.Fprintf(w, "/* %s */ .%schroma .%s { %s }\n", tt, f.prefix, class, styles); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,7 +387,7 @@ func (f *Formatter) styleToCSS(style *chroma.Style) map[chroma.TokenType]string
|
|||||||
if t != chroma.Background {
|
if t != chroma.Background {
|
||||||
entry = entry.Sub(bg)
|
entry = entry.Sub(bg)
|
||||||
}
|
}
|
||||||
if entry.IsZero() {
|
if !f.allClasses && entry.IsZero() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
classes[t] = StyleEntryToCSS(entry)
|
classes[t] = StyleEntryToCSS(entry)
|
||||||
|
51
vendor/github.com/alecthomas/chroma/formatters/svg/font_liberation_mono.go
generated
vendored
Normal file
51
vendor/github.com/alecthomas/chroma/formatters/svg/font_liberation_mono.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
222
vendor/github.com/alecthomas/chroma/formatters/svg/svg.go
generated
vendored
Normal file
222
vendor/github.com/alecthomas/chroma/formatters/svg/svg.go
generated
vendored
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
// Package svg contains an SVG formatter.
|
||||||
|
package svg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alecthomas/chroma"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option sets an option of the SVG formatter.
|
||||||
|
type Option func(f *Formatter)
|
||||||
|
|
||||||
|
// FontFamily sets the font-family.
|
||||||
|
func FontFamily(fontFamily string) Option { return func(f *Formatter) { f.fontFamily = fontFamily } }
|
||||||
|
|
||||||
|
// EmbedFontFile embeds given font file
|
||||||
|
func EmbedFontFile(fontFamily string, fileName string) (option Option, err error) {
|
||||||
|
var format FontFormat
|
||||||
|
switch path.Ext(fileName) {
|
||||||
|
case ".woff":
|
||||||
|
format = WOFF
|
||||||
|
case ".woff2":
|
||||||
|
format = WOFF2
|
||||||
|
case ".ttf":
|
||||||
|
format = TRUETYPE
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unexpected font file suffix")
|
||||||
|
}
|
||||||
|
|
||||||
|
var content []byte
|
||||||
|
if content, err = ioutil.ReadFile(fileName); err == nil {
|
||||||
|
option = EmbedFont(fontFamily, base64.StdEncoding.EncodeToString(content), format)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmbedFont embeds given base64 encoded font
|
||||||
|
func EmbedFont(fontFamily string, font string, format FontFormat) Option {
|
||||||
|
return func(f *Formatter) { f.fontFamily = fontFamily; f.embeddedFont = font; f.fontFormat = format }
|
||||||
|
}
|
||||||
|
|
||||||
|
// New SVG formatter.
|
||||||
|
func New(options ...Option) *Formatter {
|
||||||
|
f := &Formatter{fontFamily: "Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace"}
|
||||||
|
for _, option := range options {
|
||||||
|
option(f)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formatter that generates SVG.
|
||||||
|
type Formatter struct {
|
||||||
|
fontFamily string
|
||||||
|
embeddedFont string
|
||||||
|
fontFormat FontFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
||||||
|
f.writeSVG(w, style, iterator.Tokens())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var svgEscaper = strings.NewReplacer(
|
||||||
|
`&`, "&",
|
||||||
|
`<`, "<",
|
||||||
|
`>`, ">",
|
||||||
|
`"`, """,
|
||||||
|
` `, " ",
|
||||||
|
` `, "    ",
|
||||||
|
)
|
||||||
|
|
||||||
|
// EscapeString escapes special characters.
|
||||||
|
func escapeString(s string) string {
|
||||||
|
return svgEscaper.Replace(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) writeSVG(w io.Writer, style *chroma.Style, tokens []chroma.Token) { // nolint: gocyclo
|
||||||
|
svgStyles := f.styleToSVG(style)
|
||||||
|
lines := chroma.SplitTokensIntoLines(tokens)
|
||||||
|
|
||||||
|
fmt.Fprint(w, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
|
||||||
|
fmt.Fprint(w, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n")
|
||||||
|
fmt.Fprintf(w, "<svg width=\"%dpx\" height=\"%dpx\" xmlns=\"http://www.w3.org/2000/svg\">\n", 8*maxLineWidth(lines), 10+int(16.8*float64(len(lines)+1)))
|
||||||
|
|
||||||
|
if f.embeddedFont != "" {
|
||||||
|
f.writeFontStyle(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "<rect width=\"100%%\" height=\"100%%\" fill=\"%s\"/>\n", style.Get(chroma.Background).Background.String())
|
||||||
|
fmt.Fprintf(w, "<g font-family=\"%s\" font-size=\"14px\" fill=\"%s\">\n", f.fontFamily, style.Get(chroma.Text).Colour.String())
|
||||||
|
|
||||||
|
f.writeTokenBackgrounds(w, lines, style)
|
||||||
|
|
||||||
|
for index, tokens := range lines {
|
||||||
|
fmt.Fprintf(w, "<text x=\"0\" y=\"%fem\" xml:space=\"preserve\">", 1.2*float64(index+1))
|
||||||
|
|
||||||
|
for _, token := range tokens {
|
||||||
|
text := escapeString(token.String())
|
||||||
|
attr := f.styleAttr(svgStyles, token.Type)
|
||||||
|
if attr != "" {
|
||||||
|
text = fmt.Sprintf("<tspan %s>%s</tspan>", attr, text)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, text)
|
||||||
|
}
|
||||||
|
fmt.Fprint(w, "</text>")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, "\n</g>\n")
|
||||||
|
fmt.Fprint(w, "</svg>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxLineWidth(lines [][]chroma.Token) int {
|
||||||
|
maxWidth := 0
|
||||||
|
for _, tokens := range lines {
|
||||||
|
length := 0
|
||||||
|
for _, token := range tokens {
|
||||||
|
length += len(strings.Replace(token.String(), ` `, " ", -1))
|
||||||
|
}
|
||||||
|
if length > maxWidth {
|
||||||
|
maxWidth = length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no background attribute for text in SVG so simply calculate the position and text
|
||||||
|
// of tokens with a background color that differs from the default and add a rectangle for each before
|
||||||
|
// adding the token.
|
||||||
|
func (f *Formatter) writeTokenBackgrounds(w io.Writer, lines [][]chroma.Token, style *chroma.Style) {
|
||||||
|
for index, tokens := range lines {
|
||||||
|
lineLength := 0
|
||||||
|
for _, token := range tokens {
|
||||||
|
length := len(strings.Replace(token.String(), ` `, " ", -1))
|
||||||
|
tokenBackground := style.Get(token.Type).Background
|
||||||
|
if tokenBackground.IsSet() && tokenBackground != style.Get(chroma.Background).Background {
|
||||||
|
fmt.Fprintf(w, "<rect id=\"%s\" x=\"%dch\" y=\"%fem\" width=\"%dch\" height=\"1.2em\" fill=\"%s\" />\n", escapeString(token.String()), lineLength, 1.2*float64(index)+0.25, length, style.Get(token.Type).Background.String())
|
||||||
|
}
|
||||||
|
lineLength += length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FontFormat int
|
||||||
|
|
||||||
|
// https://transfonter.org/formats
|
||||||
|
const (
|
||||||
|
WOFF FontFormat = iota
|
||||||
|
WOFF2
|
||||||
|
TRUETYPE
|
||||||
|
)
|
||||||
|
|
||||||
|
var fontFormats = [...]string{
|
||||||
|
"woff",
|
||||||
|
"woff2",
|
||||||
|
"truetype",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) writeFontStyle(w io.Writer) {
|
||||||
|
fmt.Fprintf(w, `<style>
|
||||||
|
@font-face {
|
||||||
|
font-family: '%s';
|
||||||
|
src: url(data:application/x-font-%s;charset=utf-8;base64,%s) format('%s');'
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
</style>`, f.fontFamily, fontFormats[f.fontFormat], f.embeddedFont, fontFormats[f.fontFormat])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType) string {
|
||||||
|
if _, ok := styles[tt]; !ok {
|
||||||
|
tt = tt.SubCategory()
|
||||||
|
if _, ok := styles[tt]; !ok {
|
||||||
|
tt = tt.Category()
|
||||||
|
if _, ok := styles[tt]; !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return styles[tt]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Formatter) styleToSVG(style *chroma.Style) map[chroma.TokenType]string {
|
||||||
|
converted := map[chroma.TokenType]string{}
|
||||||
|
bg := style.Get(chroma.Background)
|
||||||
|
// Convert the style.
|
||||||
|
for t := range chroma.StandardTypes {
|
||||||
|
entry := style.Get(t)
|
||||||
|
if t != chroma.Background {
|
||||||
|
entry = entry.Sub(bg)
|
||||||
|
}
|
||||||
|
if entry.IsZero() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
converted[t] = StyleEntryToSVG(entry)
|
||||||
|
}
|
||||||
|
return converted
|
||||||
|
}
|
||||||
|
|
||||||
|
// StyleEntryToSVG converts a chroma.StyleEntry to SVG attributes.
|
||||||
|
func StyleEntryToSVG(e chroma.StyleEntry) string {
|
||||||
|
var styles []string
|
||||||
|
|
||||||
|
if e.Colour.IsSet() {
|
||||||
|
styles = append(styles, "fill=\""+e.Colour.String()+"\"")
|
||||||
|
}
|
||||||
|
if e.Bold == chroma.Yes {
|
||||||
|
styles = append(styles, "font-weight=\"bold\"")
|
||||||
|
}
|
||||||
|
if e.Italic == chroma.Yes {
|
||||||
|
styles = append(styles, "font-style=\"italic\"")
|
||||||
|
}
|
||||||
|
if e.Underline == chroma.Yes {
|
||||||
|
styles = append(styles, "text-decoration=\"underline\"")
|
||||||
|
}
|
||||||
|
return strings.Join(styles, " ")
|
||||||
|
}
|
17
vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go
generated
vendored
17
vendor/github.com/alecthomas/chroma/formatters/tty_indexed.go
generated
vendored
@ -200,6 +200,7 @@ func findClosest(table *ttyTable, seeking chroma.Colour) chroma.Colour {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.TokenType]string {
|
func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.TokenType]string {
|
||||||
|
style = clearBackground(style)
|
||||||
out := map[chroma.TokenType]string{}
|
out := map[chroma.TokenType]string{}
|
||||||
for _, ttype := range style.Types() {
|
for _, ttype := range style.Types() {
|
||||||
entry := style.Get(ttype)
|
entry := style.Get(ttype)
|
||||||
@ -208,16 +209,22 @@ func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.Toke
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear the background colour.
|
||||||
|
func clearBackground(style *chroma.Style) *chroma.Style {
|
||||||
|
builder := style.Builder()
|
||||||
|
bg := builder.Get(chroma.Background)
|
||||||
|
bg.Background = 0
|
||||||
|
bg.NoInherit = true
|
||||||
|
builder.AddEntry(chroma.Background, bg)
|
||||||
|
style, _ = builder.Build()
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
|
||||||
type indexedTTYFormatter struct {
|
type indexedTTYFormatter struct {
|
||||||
table *ttyTable
|
table *ttyTable
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
||||||
defer func() {
|
|
||||||
if perr := recover(); perr != nil {
|
|
||||||
err = perr.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
theme := styleToEscapeSequence(c.table, style)
|
theme := styleToEscapeSequence(c.table, style)
|
||||||
for token := it(); token != chroma.EOF; token = it() {
|
for token := it(); token != chroma.EOF; token = it() {
|
||||||
// TODO: Cache token lookups?
|
// TODO: Cache token lookups?
|
||||||
|
1
vendor/github.com/alecthomas/chroma/formatters/tty_truecolour.go
generated
vendored
1
vendor/github.com/alecthomas/chroma/formatters/tty_truecolour.go
generated
vendored
@ -11,6 +11,7 @@ import (
|
|||||||
var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter))
|
var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter))
|
||||||
|
|
||||||
func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
|
func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
|
||||||
|
style = clearBackground(style)
|
||||||
for token := it(); token != chroma.EOF; token = it() {
|
for token := it(); token != chroma.EOF; token = it() {
|
||||||
entry := style.Get(token.Type)
|
entry := style.Get(token.Type)
|
||||||
if !entry.IsZero() {
|
if !entry.IsZero() {
|
||||||
|
22
vendor/github.com/alecthomas/chroma/go.mod
generated
vendored
22
vendor/github.com/alecthomas/chroma/go.mod
generated
vendored
@ -1,22 +1,18 @@
|
|||||||
module github.com/alecthomas/chroma
|
module github.com/alecthomas/chroma
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/GeertJohan/go.rice v1.0.0
|
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 // indirect
|
||||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae
|
github.com/alecthomas/kong v0.2.4
|
||||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8
|
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect
|
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 // indirect
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
|
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
|
||||||
github.com/dlclark/regexp2 v1.1.6
|
github.com/dlclark/regexp2 v1.2.0
|
||||||
github.com/gorilla/csrf v1.6.0
|
github.com/mattn/go-colorable v0.1.6
|
||||||
github.com/gorilla/handlers v1.4.1
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/gorilla/mux v1.7.3
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/mattn/go-colorable v0.0.9
|
|
||||||
github.com/mattn/go-isatty v0.0.4
|
|
||||||
github.com/sergi/go-diff v1.0.0 // indirect
|
github.com/sergi/go-diff v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/GeertJohan/go.rice => github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7
|
|
||||||
|
50
vendor/github.com/alecthomas/chroma/go.sum
generated
vendored
50
vendor/github.com/alecthomas/chroma/go.sum
generated
vendored
@ -1,48 +1,26 @@
|
|||||||
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
|
||||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||||
github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7 h1:0cMlP9evwgTzs5JUe2C/3rLttYjmRm0kbz9fdGBIV1E=
|
github.com/alecthomas/kong v0.2.4 h1:Y0ZBCHAvHhTHw7FFJ2FzCAAG4pkbTgA45nc7BpMhDNk=
|
||||||
github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4=
|
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||||
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
|
||||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae h1:C4Q9m+oXOxcSWwYk9XzzafY2xAVAaeubZbUHJkw3PlY=
|
|
||||||
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
|
||||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8 h1:atLL+K8Hg0e8863K2X+k7qu+xz3M2a/mWFIACAPf55M=
|
|
||||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
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/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
|
|
||||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
|
||||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
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/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=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
|
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||||
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
github.com/gorilla/csrf v1.6.0 h1:60oN1cFdncCE8tjwQ3QEkFND5k37lQPcRjnlvm7CIJ0=
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/gorilla/handlers v1.4.1 h1:BHvcRGJe/TrL+OqFxoKQGddTgeibiOjaBssV5a/N9sw=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
|
||||||
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/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
|
||||||
github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc=
|
|
||||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
@ -52,7 +30,7 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 h1:YAFjXN64LMvktoUZH9zgY4lGc/msGN7HQfoSuKCgaDU=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
5
vendor/github.com/alecthomas/chroma/lexer.go
generated
vendored
5
vendor/github.com/alecthomas/chroma/lexer.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
defaultOptions = &TokeniseOptions{
|
defaultOptions = &TokeniseOptions{
|
||||||
State: "root",
|
State: "root",
|
||||||
|
EnsureLF: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -80,6 +81,10 @@ type TokeniseOptions struct {
|
|||||||
State string
|
State string
|
||||||
// Nested tokenisation.
|
// Nested tokenisation.
|
||||||
Nested bool
|
Nested bool
|
||||||
|
|
||||||
|
// If true, all EOLs are converted into LF
|
||||||
|
// by replacing CRLF and CR
|
||||||
|
EnsureLF bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Lexer for tokenising source code.
|
// A Lexer for tokenising source code.
|
||||||
|
22
vendor/github.com/alecthomas/chroma/lexers/README.md
generated
vendored
22
vendor/github.com/alecthomas/chroma/lexers/README.md
generated
vendored
@ -10,10 +10,28 @@ Run the tests as normal:
|
|||||||
go test ./lexers
|
go test ./lexers
|
||||||
```
|
```
|
||||||
|
|
||||||
## Updating the existing tests
|
## Update existing tests
|
||||||
|
When you add a new test data file (`*.actual`), you need to regenerate all tests. That's how Chroma creates the `*.expected` test file based on the corresponding lexer.
|
||||||
|
|
||||||
You can regenerate all the test outputs
|
To regenerate all tests, type in your terminal:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
RECORD=true go test ./lexers
|
RECORD=true go test ./lexers
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This first sets the `RECORD` environment variable to `true`. Then it runs `go test` on the `./lexers` directory of the Chroma project.
|
||||||
|
|
||||||
|
(That environment variable tells Chroma it needs to output test data. After running `go test ./lexers` you can remove or reset that variable.)
|
||||||
|
|
||||||
|
### Windows users
|
||||||
|
Windows users will find that the `RECORD=true go test ./lexers` command fails in both the standard command prompt terminal and in PowerShell.
|
||||||
|
|
||||||
|
Instead we have to perform both steps separately:
|
||||||
|
|
||||||
|
- Set the `RECORD` environment variable to `true`.
|
||||||
|
+ In the regular command prompt window, the `set` command sets an environment variable for the current session: `set RECORD=true`. See [this page](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line) for more.
|
||||||
|
+ In PowerShell, you can use the `$env:RECORD = 'true'` command for that. See [this article](https://mcpmag.com/articles/2019/03/28/environment-variables-in-powershell.aspx) for more.
|
||||||
|
+ You can also make a persistent environment variable by hand in the Windows computer settings. See [this article](https://www.computerhope.com/issues/ch000549.htm) for how.
|
||||||
|
- When the environment variable is set, run `go tests ./lexers`.
|
||||||
|
|
||||||
|
Chroma will now regenerate the test files and print its results to the console window.
|
||||||
|
2
vendor/github.com/alecthomas/chroma/lexers/a/applescript.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/a/applescript.go
generated
vendored
@ -31,7 +31,7 @@ var Applescript = internal.Register(MustNewLexer(
|
|||||||
{`\b(as )(alias |application |boolean |class |constant |date |file |integer |list |number |POSIX file |real |record |reference |RGB color |script |text |unit types|(?:Unicode )?text|string)\b`, ByGroups(Keyword, NameClass), nil},
|
{`\b(as )(alias |application |boolean |class |constant |date |file |integer |list |number |POSIX file |real |record |reference |RGB color |script |text |unit types|(?:Unicode )?text|string)\b`, ByGroups(Keyword, NameClass), nil},
|
||||||
{`\b(AppleScript|current application|false|linefeed|missing value|pi|quote|result|return|space|tab|text item delimiters|true|version)\b`, NameConstant, nil},
|
{`\b(AppleScript|current application|false|linefeed|missing value|pi|quote|result|return|space|tab|text item delimiters|true|version)\b`, NameConstant, nil},
|
||||||
{`\b(ASCII (character|number)|activate|beep|choose URL|choose application|choose color|choose file( name)?|choose folder|choose from list|choose remote application|clipboard info|close( access)?|copy|count|current date|delay|delete|display (alert|dialog)|do shell script|duplicate|exists|get eof|get volume settings|info for|launch|list (disks|folder)|load script|log|make|mount volume|new|offset|open( (for access|location))?|path to|print|quit|random number|read|round|run( script)?|say|scripting components|set (eof|the clipboard to|volume)|store script|summarize|system attribute|system info|the clipboard|time to GMT|write|quoted form)\b`, NameBuiltin, nil},
|
{`\b(ASCII (character|number)|activate|beep|choose URL|choose application|choose color|choose file( name)?|choose folder|choose from list|choose remote application|clipboard info|close( access)?|copy|count|current date|delay|delete|display (alert|dialog)|do shell script|duplicate|exists|get eof|get volume settings|info for|launch|list (disks|folder)|load script|log|make|mount volume|new|offset|open( (for access|location))?|path to|print|quit|random number|read|round|run( script)?|say|scripting components|set (eof|the clipboard to|volume)|store script|summarize|system attribute|system info|the clipboard|time to GMT|write|quoted form)\b`, NameBuiltin, nil},
|
||||||
{`\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|whith|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b`, Keyword, nil},
|
{`\b(considering|else|error|exit|from|if|ignoring|in|repeat|tell|then|times|to|try|until|using terms from|while|with|with timeout( of)?|with transaction|by|continue|end|its?|me|my|return|of|as)\b`, Keyword, nil},
|
||||||
{`\b(global|local|prop(erty)?|set|get)\b`, Keyword, nil},
|
{`\b(global|local|prop(erty)?|set|get)\b`, Keyword, nil},
|
||||||
{`\b(but|put|returning|the)\b`, NameBuiltin, nil},
|
{`\b(but|put|returning|the)\b`, NameBuiltin, nil},
|
||||||
{`\b(attachment|attribute run|character|day|month|paragraph|word|year)s?\b`, NameBuiltin, nil},
|
{`\b(attachment|attribute run|character|day|month|paragraph|word|year)s?\b`, NameBuiltin, nil},
|
||||||
|
10
vendor/github.com/alecthomas/chroma/lexers/a/awk.go
generated
vendored
10
vendor/github.com/alecthomas/chroma/lexers/a/awk.go
generated
vendored
@ -30,14 +30,14 @@ var Awk = internal.Register(MustNewLexer(
|
|||||||
"root": {
|
"root": {
|
||||||
{`^(?=\s|/)`, Text, Push("slashstartsregex")},
|
{`^(?=\s|/)`, Text, Push("slashstartsregex")},
|
||||||
Include("commentsandwhitespace"),
|
Include("commentsandwhitespace"),
|
||||||
{`\+\+|--|\|\||&&|in\b|\$|!?~|(\*\*|[-<>+*%\^/!=|])=?`, Operator, Push("slashstartsregex")},
|
{`\+\+|--|\|\||&&|in\b|\$|!?~|\|&|(\*\*|[-<>+*%\^/!=|])=?`, Operator, Push("slashstartsregex")},
|
||||||
{`[{(\[;,]`, Punctuation, Push("slashstartsregex")},
|
{`[{(\[;,]`, Punctuation, Push("slashstartsregex")},
|
||||||
{`[})\].]`, Punctuation, nil},
|
{`[})\].]`, Punctuation, nil},
|
||||||
{`(break|continue|do|while|exit|for|if|else|return)\b`, Keyword, Push("slashstartsregex")},
|
{`(break|continue|do|while|exit|for|if|else|return|switch|case|default)\b`, Keyword, Push("slashstartsregex")},
|
||||||
{`function\b`, KeywordDeclaration, Push("slashstartsregex")},
|
{`function\b`, KeywordDeclaration, Push("slashstartsregex")},
|
||||||
{`(atan2|cos|exp|int|log|rand|sin|sqrt|srand|gensub|gsub|index|length|match|split|sprintf|sub|substr|tolower|toupper|close|fflush|getline|next|nextfile|print|printf|strftime|systime|delete|system)\b`, KeywordReserved, nil},
|
{`(atan2|cos|exp|int|log|rand|sin|sqrt|srand|gensub|gsub|index|length|match|split|patsplit|sprintf|sub|substr|tolower|toupper|close|fflush|getline|next(file)|print|printf|strftime|systime|mktime|delete|system|strtonum|and|compl|lshift|or|rshift|asorti?|isarray|bindtextdomain|dcn?gettext|@(include|load|namespace))\b`, KeywordReserved, nil},
|
||||||
{`(ARGC|ARGIND|ARGV|BEGIN|CONVFMT|ENVIRON|END|ERRNO|FIELDWIDTHS|FILENAME|FNR|FS|IGNORECASE|NF|NR|OFMT|OFS|ORFS|RLENGTH|RS|RSTART|RT|SUBSEP)\b`, NameBuiltin, nil},
|
{`(ARGC|ARGIND|ARGV|BEGIN(FILE)?|BINMODE|CONVFMT|ENVIRON|END(FILE)?|ERRNO|FIELDWIDTHS|FILENAME|FNR|FPAT|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS|PROCINFO|RLENGTH|RS|RSTART|RT|SUBSEP|TEXTDOMAIN)\b`, NameBuiltin, nil},
|
||||||
{`[$a-zA-Z_]\w*`, NameOther, nil},
|
{`[@$a-zA-Z_]\w*`, NameOther, nil},
|
||||||
{`[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?`, LiteralNumberFloat, nil},
|
{`[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?`, LiteralNumberFloat, nil},
|
||||||
{`0x[0-9a-fA-F]+`, LiteralNumberHex, nil},
|
{`0x[0-9a-fA-F]+`, LiteralNumberHex, nil},
|
||||||
{`[0-9]+`, LiteralNumberInteger, nil},
|
{`[0-9]+`, LiteralNumberInteger, nil},
|
||||||
|
2
vendor/github.com/alecthomas/chroma/lexers/b/ballerina.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/b/ballerina.go
generated
vendored
@ -25,7 +25,7 @@ var Ballerina = internal.Register(MustNewLexer(
|
|||||||
{`(annotation|bind|but|endpoint|error|function|object|private|public|returns|service|type|var|with|worker)\b`, KeywordDeclaration, nil},
|
{`(annotation|bind|but|endpoint|error|function|object|private|public|returns|service|type|var|with|worker)\b`, KeywordDeclaration, nil},
|
||||||
{`(boolean|byte|decimal|float|int|json|map|nil|record|string|table|xml)\b`, KeywordType, nil},
|
{`(boolean|byte|decimal|float|int|json|map|nil|record|string|table|xml)\b`, KeywordType, nil},
|
||||||
{`(true|false|null)\b`, KeywordConstant, nil},
|
{`(true|false|null)\b`, KeywordConstant, nil},
|
||||||
{`import(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
{`(import)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
||||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||||
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
||||||
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
|
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
|
||||||
|
4
vendor/github.com/alecthomas/chroma/lexers/b/bash.go
generated
vendored
4
vendor/github.com/alecthomas/chroma/lexers/b/bash.go
generated
vendored
@ -36,7 +36,7 @@ var Bash = internal.Register(MustNewLexer(
|
|||||||
{`\b(if|fi|else|while|do|done|for|then|return|function|case|select|continue|until|esac|elif)(\s*)\b`, ByGroups(Keyword, Text), nil},
|
{`\b(if|fi|else|while|do|done|for|then|return|function|case|select|continue|until|esac|elif)(\s*)\b`, ByGroups(Keyword, Text), nil},
|
||||||
{"\\b(alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|declare|dirs|disown|echo|enable|eval|exec|exit|export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|time|times|trap|true|type|typeset|ulimit|umask|unalias|unset|wait)(?=[\\s)`])", NameBuiltin, nil},
|
{"\\b(alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|declare|dirs|disown|echo|enable|eval|exec|exit|export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|time|times|trap|true|type|typeset|ulimit|umask|unalias|unset|wait)(?=[\\s)`])", NameBuiltin, nil},
|
||||||
{`\A#!.+\n`, CommentPreproc, nil},
|
{`\A#!.+\n`, CommentPreproc, nil},
|
||||||
{`#.*\S`, CommentSingle, nil},
|
{`#.*(\S|$)`, CommentSingle, nil},
|
||||||
{`\\[\w\W]`, LiteralStringEscape, nil},
|
{`\\[\w\W]`, LiteralStringEscape, nil},
|
||||||
{`(\b\w+)(\s*)(\+?=)`, ByGroups(NameVariable, Text, Operator), nil},
|
{`(\b\w+)(\s*)(\+?=)`, ByGroups(NameVariable, Text, Operator), nil},
|
||||||
{`[\[\]{}()=]`, Operator, nil},
|
{`[\[\]{}()=]`, Operator, nil},
|
||||||
@ -53,7 +53,7 @@ var Bash = internal.Register(MustNewLexer(
|
|||||||
{`&`, Punctuation, nil},
|
{`&`, Punctuation, nil},
|
||||||
{`\|`, Punctuation, nil},
|
{`\|`, Punctuation, nil},
|
||||||
{`\s+`, Text, nil},
|
{`\s+`, Text, nil},
|
||||||
{`\d+\b`, LiteralNumber, nil},
|
{`\d+(?= |$)`, LiteralNumber, nil},
|
||||||
{"[^=\\s\\[\\]{}()$\"\\'`\\\\<&|;]+", Text, nil},
|
{"[^=\\s\\[\\]{}()$\"\\'`\\\\<&|;]+", Text, nil},
|
||||||
{`<`, Text, nil},
|
{`<`, Text, nil},
|
||||||
},
|
},
|
||||||
|
76
vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go
generated
vendored
Normal file
76
vendor/github.com/alecthomas/chroma/lexers/b/bibtex.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package b
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bibtex lexer.
|
||||||
|
var Bibtex = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "BibTeX",
|
||||||
|
Aliases: []string{"bib", "bibtex"},
|
||||||
|
Filenames: []string{"*.bib"},
|
||||||
|
MimeTypes: []string{"text/x-bibtex"},
|
||||||
|
NotMultiline: true,
|
||||||
|
CaseInsensitive: true,
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`@comment`, Comment, nil},
|
||||||
|
{`@preamble`, NameClass, Push("closing-brace", "value", "opening-brace")},
|
||||||
|
{`@string`, NameClass, Push("closing-brace", "field", "opening-brace")},
|
||||||
|
{"@[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameClass, Push("closing-brace", "command-body", "opening-brace")},
|
||||||
|
{`.+`, Comment, nil},
|
||||||
|
},
|
||||||
|
"opening-brace": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`[{(]`, Punctuation, Pop(1)},
|
||||||
|
},
|
||||||
|
"closing-brace": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`[})]`, Punctuation, Pop(1)},
|
||||||
|
},
|
||||||
|
"command-body": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`[^\s\,\}]+`, NameLabel, Push("#pop", "fields")},
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`,`, Punctuation, Push("field")},
|
||||||
|
Default(Pop(1)),
|
||||||
|
},
|
||||||
|
"field": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{"[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameAttribute, Push("value", "=")},
|
||||||
|
Default(Pop(1)),
|
||||||
|
},
|
||||||
|
"=": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`=`, Punctuation, Pop(1)},
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{"[a-z_@!$&*+\\-./:;<>?\\[\\\\\\]^`|~][\\w@!$&*+\\-./:;<>?\\[\\\\\\]^`|~]*", NameVariable, nil},
|
||||||
|
{`"`, LiteralString, Push("quoted-string")},
|
||||||
|
{`\{`, LiteralString, Push("braced-string")},
|
||||||
|
{`[\d]+`, LiteralNumber, nil},
|
||||||
|
{`#`, Punctuation, nil},
|
||||||
|
Default(Pop(1)),
|
||||||
|
},
|
||||||
|
"quoted-string": {
|
||||||
|
{`\{`, LiteralString, Push("braced-string")},
|
||||||
|
{`"`, LiteralString, Pop(1)},
|
||||||
|
{`[^\{\"]+`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"braced-string": {
|
||||||
|
{`\{`, LiteralString, Push()},
|
||||||
|
{`\}`, LiteralString, Pop(1)},
|
||||||
|
{`[^\{\}]+`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"whitespace": {
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
206
vendor/github.com/alecthomas/chroma/lexers/c/caddyfile.go
generated
vendored
Normal file
206
vendor/github.com/alecthomas/chroma/lexers/c/caddyfile.go
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package c
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// caddyfileCommon are the rules common to both of the lexer variants
|
||||||
|
var caddyfileCommon = Rules{
|
||||||
|
"site_block_common": {
|
||||||
|
// Import keyword
|
||||||
|
{`(import)(\s+)([^\s]+)`, ByGroups(Keyword, Text, NameVariableMagic), nil},
|
||||||
|
// Matcher definition
|
||||||
|
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||||
|
// Matcher token stub for docs
|
||||||
|
{`\[\<matcher\>\]`, NameDecorator, Push("matcher")},
|
||||||
|
// These cannot have matchers but may have things that look like
|
||||||
|
// matchers in their arguments, so we just parse as a subdirective.
|
||||||
|
{`try_files`, Keyword, Push("subdirective")},
|
||||||
|
// These are special, they can nest more directives
|
||||||
|
{`handle_errors|handle|route|handle_path|not`, Keyword, Push("nested_directive")},
|
||||||
|
// Any other directive
|
||||||
|
{`[^\s#]+`, Keyword, Push("directive")},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"matcher": {
|
||||||
|
{`\{`, Punctuation, Push("block")},
|
||||||
|
// Not can be one-liner
|
||||||
|
{`not`, Keyword, Push("deep_not_matcher")},
|
||||||
|
// Any other same-line matcher
|
||||||
|
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||||
|
// Terminators
|
||||||
|
{`\n`, Text, Pop(1)},
|
||||||
|
{`\}`, Punctuation, Pop(1)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"block": {
|
||||||
|
{`\}`, Punctuation, Pop(2)},
|
||||||
|
// Not can be one-liner
|
||||||
|
{`not`, Keyword, Push("not_matcher")},
|
||||||
|
// Any other subdirective
|
||||||
|
{`[^\s#]+`, Keyword, Push("subdirective")},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"nested_block": {
|
||||||
|
{`\}`, Punctuation, Pop(2)},
|
||||||
|
// Matcher definition
|
||||||
|
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||||
|
// Something that starts with literally < is probably a docs stub
|
||||||
|
{`\<[^#]+\>`, Keyword, Push("nested_directive")},
|
||||||
|
// Any other directive
|
||||||
|
{`[^\s#]+`, Keyword, Push("nested_directive")},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"not_matcher": {
|
||||||
|
{`\}`, Punctuation, Pop(2)},
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
{`[^\s#]+`, Keyword, Push("arguments")},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
"deep_not_matcher": {
|
||||||
|
{`\}`, Punctuation, Pop(2)},
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
{`[^\s#]+`, Keyword, Push("deep_subdirective")},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
"directive": {
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
Include("matcher_token"),
|
||||||
|
Include("comments_pop_1"),
|
||||||
|
{`\n`, Text, Pop(1)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"nested_directive": {
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("nested_block")},
|
||||||
|
Include("matcher_token"),
|
||||||
|
Include("comments_pop_1"),
|
||||||
|
{`\n`, Text, Pop(1)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"subdirective": {
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
Include("comments_pop_1"),
|
||||||
|
{`\n`, Text, Pop(1)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"arguments": {
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
Include("comments_pop_2"),
|
||||||
|
{`\\\n`, Text, nil}, // Skip escaped newlines
|
||||||
|
{`\n`, Text, Pop(2)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"deep_subdirective": {
|
||||||
|
{`\{(?=\s)`, Punctuation, Push("block")},
|
||||||
|
Include("comments_pop_3"),
|
||||||
|
{`\n`, Text, Pop(3)},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"matcher_token": {
|
||||||
|
{`@[^\s]+`, NameDecorator, Push("arguments")}, // Named matcher
|
||||||
|
{`/[^\s]+`, NameDecorator, Push("arguments")}, // Path matcher
|
||||||
|
{`\*`, NameDecorator, Push("arguments")}, // Wildcard path matcher
|
||||||
|
{`\[\<matcher\>\]`, NameDecorator, Push("arguments")}, // Matcher token stub for docs
|
||||||
|
},
|
||||||
|
"comments": {
|
||||||
|
{`^#.*\n`, CommentSingle, nil}, // Comment at start of line
|
||||||
|
{`\s+#.*\n`, CommentSingle, nil}, // Comment preceded by whitespace
|
||||||
|
},
|
||||||
|
"comments_pop_1": {
|
||||||
|
{`^#.*\n`, CommentSingle, Pop(1)}, // Comment at start of line
|
||||||
|
{`\s+#.*\n`, CommentSingle, Pop(1)}, // Comment preceded by whitespace
|
||||||
|
},
|
||||||
|
"comments_pop_2": {
|
||||||
|
{`^#.*\n`, CommentSingle, Pop(2)}, // Comment at start of line
|
||||||
|
{`\s+#.*\n`, CommentSingle, Pop(2)}, // Comment preceded by whitespace
|
||||||
|
},
|
||||||
|
"comments_pop_3": {
|
||||||
|
{`^#.*\n`, CommentSingle, Pop(3)}, // Comment at start of line
|
||||||
|
{`\s+#.*\n`, CommentSingle, Pop(3)}, // Comment preceded by whitespace
|
||||||
|
},
|
||||||
|
"base": {
|
||||||
|
Include("comments"),
|
||||||
|
{`(on|off|first|last|before|after|internal|strip_prefix|strip_suffix|replace)\b`, NameConstant, nil},
|
||||||
|
{`(https?://)?([a-z0-9.-]+)(:)([0-9]+)`, ByGroups(Name, Name, Punctuation, LiteralNumberInteger), nil},
|
||||||
|
{`[a-z-]+/[a-z-+]+`, LiteralString, nil},
|
||||||
|
{`[0-9]+[km]?\b`, LiteralNumberInteger, nil},
|
||||||
|
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil}, // Placeholder
|
||||||
|
{`\[(?=[^#{}$]+\])`, Punctuation, nil},
|
||||||
|
{`\]|\|`, Punctuation, nil},
|
||||||
|
{`[^\s#{}$\]]+`, LiteralString, nil},
|
||||||
|
{`/[^\s#]*`, Name, nil},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caddyfile lexer.
|
||||||
|
var Caddyfile = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "Caddyfile",
|
||||||
|
Aliases: []string{"caddyfile", "caddy"},
|
||||||
|
Filenames: []string{"Caddyfile*"},
|
||||||
|
MimeTypes: []string{},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
Include("comments"),
|
||||||
|
// Global options block
|
||||||
|
{`^\s*(\{)\s*$`, ByGroups(Punctuation), Push("globals")},
|
||||||
|
// Snippets
|
||||||
|
{`(\([^\s#]+\))(\s*)(\{)`, ByGroups(NameVariableAnonymous, Text, Punctuation), Push("snippet")},
|
||||||
|
// Site label
|
||||||
|
{`[^#{(\s,]+`, GenericHeading, Push("label")},
|
||||||
|
// Site label with placeholder
|
||||||
|
{`\{[\w+.\$-]+\}`, LiteralStringEscape, Push("label")},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
{`\}`, Punctuation, Pop(1)},
|
||||||
|
{`[^\s#]+`, Keyword, Push("directive")},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"snippet": {
|
||||||
|
{`\}`, Punctuation, Pop(1)},
|
||||||
|
// Matcher definition
|
||||||
|
{`@[^\s]+(?=\s)`, NameDecorator, Push("matcher")},
|
||||||
|
// Any directive
|
||||||
|
{`[^\s#]+`, Keyword, Push("directive")},
|
||||||
|
Include("base"),
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
// Allow multiple labels, comma separated, newlines after
|
||||||
|
// a comma means another label is coming
|
||||||
|
{`,\s*\n?`, Text, nil},
|
||||||
|
{` `, Text, nil},
|
||||||
|
// Site label with placeholder
|
||||||
|
{`\{[\w+.\$-]+\}`, LiteralStringEscape, nil},
|
||||||
|
// Site label
|
||||||
|
{`[^#{(\s,]+`, GenericHeading, nil},
|
||||||
|
// Comment after non-block label (hack because comments end in \n)
|
||||||
|
{`#.*\n`, CommentSingle, Push("site_block")},
|
||||||
|
// Note: if \n, we'll never pop out of the site_block, it's valid
|
||||||
|
{`\{(?=\s)|\n`, Punctuation, Push("site_block")},
|
||||||
|
},
|
||||||
|
"site_block": {
|
||||||
|
{`\}`, Punctuation, Pop(2)},
|
||||||
|
Include("site_block_common"),
|
||||||
|
},
|
||||||
|
}.Merge(caddyfileCommon),
|
||||||
|
))
|
||||||
|
|
||||||
|
// Caddyfile directive-only lexer.
|
||||||
|
var CaddyfileDirectives = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "Caddyfile Directives",
|
||||||
|
Aliases: []string{"caddyfile-directives", "caddyfile-d", "caddy-d"},
|
||||||
|
Filenames: []string{},
|
||||||
|
MimeTypes: []string{},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
// Same as "site_block" in Caddyfile
|
||||||
|
"root": {
|
||||||
|
Include("site_block_common"),
|
||||||
|
},
|
||||||
|
}.Merge(caddyfileCommon),
|
||||||
|
))
|
3
vendor/github.com/alecthomas/chroma/lexers/c/cpp.go
generated
vendored
3
vendor/github.com/alecthomas/chroma/lexers/c/cpp.go
generated
vendored
@ -24,7 +24,8 @@ var CPP = internal.Register(MustNewLexer(
|
|||||||
{`(u8|u|U)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
|
{`(u8|u|U)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
|
||||||
{`(L?)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
|
{`(L?)(")`, ByGroups(LiteralStringAffix, LiteralString), Push("string")},
|
||||||
{`(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')`, ByGroups(LiteralStringAffix, LiteralStringChar, LiteralStringChar, LiteralStringChar), nil},
|
{`(L?)(')(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])(')`, ByGroups(LiteralStringAffix, LiteralStringChar, LiteralStringChar, LiteralStringChar), nil},
|
||||||
{`(\.([0-9](?:'?[0-9]+)*)([eE][+-]?([0-9]('?[0-9]+)*))?|([0-9]('?[0-9]+)*)(([eE][+-]?([0-9]('?[0-9]+)*))|\.([0-9]('?[0-9]+)*)?([eE][+-]?([0-9]('?[0-9]+)*))?)|0[xX](\.([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)([pP][-+]?([0-9]('?[0-9]+)*))?|([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)(([pP][-+]?([0-9]('?[0-9]+)*))|\.([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)?([pP][-+]?([0-9]('?[0-9]+)*))?)))[fFLlUu]*`, LiteralNumberFloat, nil},
|
{`(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[LlUu]*`, LiteralNumberFloat, nil},
|
||||||
|
{`(\d+\.\d*|\.\d+|\d+[fF])[fF]?`, LiteralNumberFloat, nil},
|
||||||
{`0[xX]([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)[LlUu]*`, LiteralNumberHex, nil},
|
{`0[xX]([0-9A-Fa-f]('?[0-9A-Fa-f]+)*)[LlUu]*`, LiteralNumberHex, nil},
|
||||||
{`0('?[0-7]+)+[LlUu]*`, LiteralNumberOct, nil},
|
{`0('?[0-7]+)+[LlUu]*`, LiteralNumberOct, nil},
|
||||||
{`0[Bb][01]('?[01]+)*[LlUu]*`, LiteralNumberBin, nil},
|
{`0[Bb][01]('?[01]+)*[LlUu]*`, LiteralNumberBin, nil},
|
||||||
|
25
vendor/github.com/alecthomas/chroma/lexers/circular/php.go
generated
vendored
25
vendor/github.com/alecthomas/chroma/lexers/circular/php.go
generated
vendored
@ -1,15 +1,12 @@
|
|||||||
package circular
|
package circular
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
. "github.com/alecthomas/chroma" // nolint
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
"github.com/alecthomas/chroma/lexers/h"
|
|
||||||
"github.com/alecthomas/chroma/lexers/internal"
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PHP lexer.
|
// PHP lexer for pure PHP code (not embedded in HTML).
|
||||||
var PHP = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
var PHP = internal.Register(MustNewLexer(
|
||||||
&Config{
|
&Config{
|
||||||
Name: "PHP",
|
Name: "PHP",
|
||||||
Aliases: []string{"php", "php3", "php4", "php5"},
|
Aliases: []string{"php", "php3", "php4", "php5"},
|
||||||
@ -19,12 +16,10 @@ var PHP = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
|||||||
CaseInsensitive: true,
|
CaseInsensitive: true,
|
||||||
EnsureNL: true,
|
EnsureNL: true,
|
||||||
},
|
},
|
||||||
Rules{
|
phpCommonRules.Rename("php", "root"),
|
||||||
"root": {
|
))
|
||||||
{`<\?(php)?`, CommentPreproc, Push("php")},
|
|
||||||
{`[^<]+`, Other, nil},
|
var phpCommonRules = Rules{
|
||||||
{`<`, Other, nil},
|
|
||||||
},
|
|
||||||
"php": {
|
"php": {
|
||||||
{`\?>`, CommentPreproc, Pop(1)},
|
{`\?>`, CommentPreproc, Pop(1)},
|
||||||
{`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil},
|
{`(<<<)([\'"]?)((?:[\\_a-z]|[^\x00-\x7f])(?:[\\\w]|[^\x00-\x7f])*)(\2\n.*?\n\s*)(\3)(;?)(\n)`, ByGroups(LiteralString, LiteralString, LiteralStringDelimiter, LiteralString, LiteralStringDelimiter, Punctuation, Text), nil},
|
||||||
@ -82,10 +77,4 @@ var PHP = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
|||||||
{`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil},
|
{`(\$\{)(\S+)(\})`, ByGroups(LiteralStringInterpol, NameVariable, LiteralStringInterpol), nil},
|
||||||
{`[${\\]`, LiteralStringDouble, nil},
|
{`[${\\]`, LiteralStringDouble, nil},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
).SetAnalyser(func(text string) float32 {
|
|
||||||
if strings.Contains(text, "<?php") {
|
|
||||||
return 0.5
|
|
||||||
}
|
|
||||||
return 0.0
|
|
||||||
})))
|
|
||||||
|
34
vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go
generated
vendored
Normal file
34
vendor/github.com/alecthomas/chroma/lexers/circular/phtml.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package circular
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/h"
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PHTML lexer is PHP in HTML.
|
||||||
|
var PHTML = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "PHTML",
|
||||||
|
Aliases: []string{"phtml"},
|
||||||
|
Filenames: []string{"*.phtml"},
|
||||||
|
MimeTypes: []string{"application/x-php", "application/x-httpd-php", "application/x-httpd-php3", "application/x-httpd-php4", "application/x-httpd-php5"},
|
||||||
|
DotAll: true,
|
||||||
|
CaseInsensitive: true,
|
||||||
|
EnsureNL: true,
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
{`<\?(php)?`, CommentPreproc, Push("php")},
|
||||||
|
{`[^<]+`, Other, nil},
|
||||||
|
{`<`, Other, nil},
|
||||||
|
},
|
||||||
|
}.Merge(phpCommonRules),
|
||||||
|
).SetAnalyser(func(text string) float32 {
|
||||||
|
if strings.Contains(text, "<?php") {
|
||||||
|
return 0.5
|
||||||
|
}
|
||||||
|
return 0.0
|
||||||
|
})))
|
2
vendor/github.com/alecthomas/chroma/lexers/d/docker.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/d/docker.go
generated
vendored
@ -22,7 +22,7 @@ var Docker = internal.Register(MustNewLexer(
|
|||||||
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`(HEALTHCHECK)(((?:\s*\\?\s*)--\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(HEALTHCHECK)(((?:\s*\\?\s*)--\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`(VOLUME|ENTRYPOINT|CMD|SHELL)((?:\s*\\?\s*))(\[.*?\])`, ByGroups(Keyword, Using(b.Bash), Using(j.JSON)), nil},
|
{`(VOLUME|ENTRYPOINT|CMD|SHELL)((?:\s*\\?\s*))(\[.*?\])`, ByGroups(Keyword, Using(b.Bash), Using(j.JSON)), nil},
|
||||||
{`(LABEL|ENV|ARG)(((?:\s*\\?\s*)\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(LABEL|ENV|ARG)((?:(?:\s*\\?\s*)\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`((?:FROM|MAINTAINER|EXPOSE|WORKDIR|USER|STOPSIGNAL)|VOLUME)\b(.*)`, ByGroups(Keyword, LiteralString), nil},
|
{`((?:FROM|MAINTAINER|EXPOSE|WORKDIR|USER|STOPSIGNAL)|VOLUME)\b(.*)`, ByGroups(Keyword, LiteralString), nil},
|
||||||
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
|
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
|
||||||
{`(.*\\\n)*.+`, Using(b.Bash), nil},
|
{`(.*\\\n)*.+`, Using(b.Bash), nil},
|
||||||
|
7
vendor/github.com/alecthomas/chroma/lexers/e/elixir.go
generated
vendored
7
vendor/github.com/alecthomas/chroma/lexers/e/elixir.go
generated
vendored
@ -28,6 +28,13 @@ var Elixir = internal.Register(MustNewLexer(
|
|||||||
{`:"`, LiteralStringSymbol, Push("string_double_atom")},
|
{`:"`, LiteralStringSymbol, Push("string_double_atom")},
|
||||||
{`:'`, LiteralStringSymbol, Push("string_single_atom")},
|
{`:'`, LiteralStringSymbol, Push("string_single_atom")},
|
||||||
{`((?:\.\.\.|<<>>|%\{\}|%|\{\})|(?:(?:\.\.\.|[a-z_]\w*[!?]?)|[A-Z]\w*(?:\.[A-Z]\w*)*|(?:\<\<\<|\>\>\>|\|\|\||\&\&\&|\^\^\^|\~\~\~|\=\=\=|\!\=\=|\~\>\>|\<\~\>|\|\~\>|\<\|\>|\=\=|\!\=|\<\=|\>\=|\&\&|\|\||\<\>|\+\+|\-\-|\|\>|\=\~|\-\>|\<\-|\||\.|\=|\~\>|\<\~|\<|\>|\+|\-|\*|\/|\!|\^|\&)))(:)(?=\s|\n)`, ByGroups(LiteralStringSymbol, Punctuation), nil},
|
{`((?:\.\.\.|<<>>|%\{\}|%|\{\})|(?:(?:\.\.\.|[a-z_]\w*[!?]?)|[A-Z]\w*(?:\.[A-Z]\w*)*|(?:\<\<\<|\>\>\>|\|\|\||\&\&\&|\^\^\^|\~\~\~|\=\=\=|\!\=\=|\~\>\>|\<\~\>|\|\~\>|\<\|\>|\=\=|\!\=|\<\=|\>\=|\&\&|\|\||\<\>|\+\+|\-\-|\|\>|\=\~|\-\>|\<\-|\||\.|\=|\~\>|\<\~|\<|\>|\+|\-|\*|\/|\!|\^|\&)))(:)(?=\s|\n)`, ByGroups(LiteralStringSymbol, Punctuation), nil},
|
||||||
|
{`(fn|do|end|after|else|rescue|catch)\b`, Keyword, nil},
|
||||||
|
{`(not|and|or|when|in)\b`, OperatorWord, nil},
|
||||||
|
{`(case|cond|for|if|unless|try|receive|raise|quote|unquote|unquote_splicing|throw|super|while)\b`, Keyword, nil},
|
||||||
|
{`(def|defp|defmodule|defprotocol|defmacro|defmacrop|defdelegate|defexception|defstruct|defimpl|defcallback)\b`, KeywordDeclaration, nil},
|
||||||
|
{`(import|require|use|alias)\b`, KeywordNamespace, nil},
|
||||||
|
{`(nil|true|false)\b`, NameConstant, nil},
|
||||||
|
{`(_|__MODULE__|__DIR__|__ENV__|__CALLER__)\b`, NamePseudo, nil},
|
||||||
{`@(?:\.\.\.|[a-z_]\w*[!?]?)`, NameAttribute, nil},
|
{`@(?:\.\.\.|[a-z_]\w*[!?]?)`, NameAttribute, nil},
|
||||||
{`(?:\.\.\.|[a-z_]\w*[!?]?)`, Name, nil},
|
{`(?:\.\.\.|[a-z_]\w*[!?]?)`, Name, nil},
|
||||||
{`(%?)([A-Z]\w*(?:\.[A-Z]\w*)*)`, ByGroups(Punctuation, NameClass), nil},
|
{`(%?)([A-Z]\w*(?:\.[A-Z]\w*)*)`, ByGroups(Punctuation, NameClass), nil},
|
||||||
|
118
vendor/github.com/alecthomas/chroma/lexers/g/gherkin.go
generated
vendored
Normal file
118
vendor/github.com/alecthomas/chroma/lexers/g/gherkin.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package g
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
var stepKeywords = `^(\s*)(하지만|조건|먼저|만일|만약|단|그리고|그러면|那麼|那么|而且|當|当|前提|假設|假设|假如|假定|但是|但し|並且|并且|同時|同时|もし|ならば|ただし|しかし|かつ|و |متى |لكن |عندما |ثم |بفرض |اذاً |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Унда |То |Припустимо, що |Припустимо |Онда |Но |Нехай |Лекин |Когато |Када |Кад |К тому же |И |Задато |Задати |Задате |Если |Допустим |Дадено |Ва |Бирок |Аммо |Али |Але |Агар |А |І |Și |És |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Youse know when youse got |Youse know like when |Yna |Ya know how |Ya gotta |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |Và |Ve |Und |Un |Thì |Then y'all |Then |Tapi |Tak |Tada |Tad |Så |Stel |Soit |Siis |Si |Sed |Se |Quando |Quand |Quan |Pryd |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Når |När |Niin |Nhưng |N |Mutta |Men |Mas |Maka |Majd |Mais |Maar |Ma |Lorsque |Lorsqu'|Kun |Kuid |Kui |Khi |Keď |Ketika |Když |Kaj |Kai |Kada |Kad |Jeżeli |Ja |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben sei |Fakat |Eğer ki |Etant donné |Et |Então |Entonces |Entao |En |Eeldades |E |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Dengan |Den youse gotta |De |Dato |Dar |Dann |Dan |Dado |Dacă |Daca |DEN |Când |Cuando |Cho |Cept |Cand |Cal |But y'all |But |Buh |Biết |Bet |BUT |Atès |Atunci |Atesa |Anrhegedig a |Angenommen |And y'all |And |An |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Aber |AN |A také |A |\* )`
|
||||||
|
|
||||||
|
var featureKeywords = `^(기능|機能|功能|フィーチャ|خاصية|תכונה|Функціонал|Функционалност|Функционал|Фича|Особина|Могућност|Özellik|Właściwość|Tính năng|Trajto|Savybė|Požiadavka|Požadavek|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Fīča|Funzionalità|Funktionalität|Funkcionalnost|Funkcionalitāte|Funcționalitate|Functionaliteit|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Feature|Egenskap|Egenskab|Crikey|Característica|Arwedd)(:)(.*)$`
|
||||||
|
|
||||||
|
var featureElementKeywords = `^(\s*)(시나리오 개요|시나리오|배경|背景|場景大綱|場景|场景大纲|场景|劇本大綱|劇本|剧本大纲|剧本|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|シナリオ|سيناريو مخطط|سيناريو|الخلفية|תרחיש|תבנית תרחיש|רקע|Тарих|Сценарій|Сценарио|Сценарий структураси|Сценарий|Структура сценарію|Структура сценарија|Структура сценария|Скица|Рамка на сценарий|Пример|Предыстория|Предистория|Позадина|Передумова|Основа|Концепт|Контекст|Założenia|Wharrimean is|Tình huống|The thing of it is|Tausta|Taust|Tapausaihio|Tapaus|Szenariogrundriss|Szenario|Szablon scenariusza|Stsenaarium|Struktura scenarija|Skica|Skenario konsep|Skenario|Situācija|Senaryo taslağı|Senaryo|Scénář|Scénario|Schema dello scenario|Scenārijs pēc parauga|Scenārijs|Scenár|Scenaro|Scenariusz|Scenariul de şablon|Scenariul de sablon|Scenariu|Scenario Outline|Scenario Amlinellol|Scenario|Scenarijus|Scenarijaus šablonas|Scenarij|Scenarie|Rerefons|Raamstsenaarium|Primer|Pozadí|Pozadina|Pozadie|Plan du scénario|Plan du Scénario|Osnova scénáře|Osnova|Náčrt Scénáře|Náčrt Scenáru|Mate|MISHUN SRSLY|MISHUN|Kịch bản|Konturo de la scenaro|Kontext|Konteksts|Kontekstas|Kontekst|Koncept|Khung tình huống|Khung kịch bản|Háttér|Grundlage|Geçmiş|Forgatókönyv vázlat|Forgatókönyv|Fono|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Escenario|Escenari|Dis is what went down|Dasar|Contexto|Contexte|Contesto|Condiţii|Conditii|Cenário|Cenario|Cefndir|Bối cảnh|Blokes|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|All y'all|Achtergrond|Abstrakt Scenario|Abstract Scenario)(:)(.*)$`
|
||||||
|
|
||||||
|
var examplesKeywords = `^(\s*)(예|例子|例|サンプル|امثلة|דוגמאות|Сценарији|Примери|Приклади|Мисоллар|Значения|Örnekler|Voorbeelden|Variantai|Tapaukset|Scenarios|Scenariji|Scenarijai|Příklady|Példák|Príklady|Przykłady|Primjeri|Primeri|Piemēri|Pavyzdžiai|Paraugs|Juhtumid|Exemplos|Exemples|Exemplele|Exempel|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|EXAMPLZ|Dữ liệu|Contoh|Cobber|Beispiele)(:)(.*)$`
|
||||||
|
|
||||||
|
// Gherkin lexer.
|
||||||
|
var Gherkin = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "Gherkin",
|
||||||
|
Aliases: []string{"cucumber", "Cucumber", "gherkin", "Gherkin"},
|
||||||
|
Filenames: []string{"*.feature", "*.FEATURE"},
|
||||||
|
MimeTypes: []string{"text/x-gherkin"},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"comments": {
|
||||||
|
{`\s*#.*$`, Comment, nil},
|
||||||
|
},
|
||||||
|
"featureElements": {
|
||||||
|
{stepKeywords, Keyword, Push("stepContentStack")},
|
||||||
|
Include("comments"),
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
"featureElementsOnStack": {
|
||||||
|
{stepKeywords, Keyword, Pop(2)},
|
||||||
|
Include("comments"),
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
"examplesTable": {
|
||||||
|
{`\s+\|`, Keyword, Push("examplesTableHeader")},
|
||||||
|
Include("comments"),
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
"examplesTableHeader": {
|
||||||
|
{`\s+\|\s*$`, Keyword, Pop(2)},
|
||||||
|
Include("comments"),
|
||||||
|
{`\\\|`, NameVariable, nil},
|
||||||
|
{`\s*\|`, Keyword, nil},
|
||||||
|
{`[^|]`, NameVariable, nil},
|
||||||
|
},
|
||||||
|
"scenarioSectionsOnStack": {
|
||||||
|
{featureElementKeywords, ByGroups(NameFunction, Keyword, Keyword, NameFunction), Push("featureElementsOnStack")},
|
||||||
|
},
|
||||||
|
"narrative": {
|
||||||
|
Include("scenarioSectionsOnStack"),
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
"tableVars": {
|
||||||
|
{`(<[^>]+>)`, NameVariable, nil},
|
||||||
|
},
|
||||||
|
"numbers": {
|
||||||
|
{`(\d+\.?\d*|\d*\.\d+)([eE][+-]?[0-9]+)?`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
Include("tableVars"),
|
||||||
|
{`(\s|.)`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"pyString": {
|
||||||
|
{`"""`, Keyword, Pop(1)},
|
||||||
|
Include("string"),
|
||||||
|
},
|
||||||
|
"stepContentRoot": {
|
||||||
|
{`$`, Keyword, Pop(1)},
|
||||||
|
Include("stepContent"),
|
||||||
|
},
|
||||||
|
"stepContentStack": {
|
||||||
|
{`$`, Keyword, Pop(2)},
|
||||||
|
Include("stepContent"),
|
||||||
|
},
|
||||||
|
"stepContent": {
|
||||||
|
{`"`, NameFunction, Push("doubleString")},
|
||||||
|
Include("tableVars"),
|
||||||
|
Include("numbers"),
|
||||||
|
Include("comments"),
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
"tableContent": {
|
||||||
|
{`\s+\|\s*$`, Keyword, Pop(1)},
|
||||||
|
Include("comments"),
|
||||||
|
{`\\\|`, LiteralString, nil},
|
||||||
|
{`\s*\|`, Keyword, nil},
|
||||||
|
{`"`, LiteralString, Push("doubleStringTable")},
|
||||||
|
Include("string"),
|
||||||
|
},
|
||||||
|
"doubleString": {
|
||||||
|
{`"`, NameFunction, Pop(1)},
|
||||||
|
Include("string"),
|
||||||
|
},
|
||||||
|
"doubleStringTable": {
|
||||||
|
{`"`, LiteralString, Pop(1)},
|
||||||
|
Include("string"),
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
{`\n`, NameFunction, nil},
|
||||||
|
Include("comments"),
|
||||||
|
{`"""`, Keyword, Push("pyString")},
|
||||||
|
{`\s+\|`, Keyword, Push("tableContent")},
|
||||||
|
{`"`, NameFunction, Push("doubleString")},
|
||||||
|
Include("tableVars"),
|
||||||
|
Include("numbers"),
|
||||||
|
{`(\s*)(@[^@\r\n\t ]+)`, ByGroups(NameFunction, NameTag), nil},
|
||||||
|
{stepKeywords, ByGroups(NameFunction, Keyword), Push("stepContentRoot")},
|
||||||
|
{featureKeywords, ByGroups(Keyword, Keyword, NameFunction), Push("narrative")},
|
||||||
|
{featureElementKeywords, ByGroups(NameFunction, Keyword, Keyword, NameFunction), Push("featureElements")},
|
||||||
|
{examplesKeywords, ByGroups(NameFunction, Keyword, Keyword, NameFunction), Push("examplesTable")},
|
||||||
|
{`(\s|.)`, NameFunction, nil},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
1
vendor/github.com/alecthomas/chroma/lexers/g/go.go
generated
vendored
1
vendor/github.com/alecthomas/chroma/lexers/g/go.go
generated
vendored
@ -15,6 +15,7 @@ var Go = internal.Register(MustNewLexer(
|
|||||||
Aliases: []string{"go", "golang"},
|
Aliases: []string{"go", "golang"},
|
||||||
Filenames: []string{"*.go"},
|
Filenames: []string{"*.go"},
|
||||||
MimeTypes: []string{"text/x-gosrc"},
|
MimeTypes: []string{"text/x-gosrc"},
|
||||||
|
EnsureNL: true,
|
||||||
},
|
},
|
||||||
Rules{
|
Rules{
|
||||||
"root": {
|
"root": {
|
||||||
|
9
vendor/github.com/alecthomas/chroma/lexers/h/http.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/lexers/h/http.go
generated
vendored
@ -19,8 +19,8 @@ var HTTP = internal.Register(httpBodyContentTypeLexer(MustNewLexer(
|
|||||||
},
|
},
|
||||||
Rules{
|
Rules{
|
||||||
"root": {
|
"root": {
|
||||||
{`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)(1\.[01])(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")},
|
{`(GET|POST|PUT|DELETE|HEAD|OPTIONS|TRACE|PATCH|CONNECT)( +)([^ ]+)( +)(HTTP)(/)([12]\.[01])(\r?\n|\Z)`, ByGroups(NameFunction, Text, NameNamespace, Text, KeywordReserved, Operator, LiteralNumber, Text), Push("headers")},
|
||||||
{`(HTTP)(/)(1\.[01])( +)(\d{3})( +)([^\r\n]+)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")},
|
{`(HTTP)(/)([12]\.[01])( +)(\d{3})( +)([^\r\n]+)(\r?\n|\Z)`, ByGroups(KeywordReserved, Operator, LiteralNumber, Text, LiteralNumber, Text, NameException, Text), Push("headers")},
|
||||||
},
|
},
|
||||||
"headers": {
|
"headers": {
|
||||||
{`([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpHeaderBlock), nil},
|
{`([^\s:]+)( *)(:)( *)([^\r\n]+)(\r?\n|\Z)`, EmitterFunc(httpHeaderBlock), nil},
|
||||||
@ -38,7 +38,6 @@ func httpContentBlock(groups []string, lexer Lexer) Iterator {
|
|||||||
{Generic, groups[0]},
|
{Generic, groups[0]},
|
||||||
}
|
}
|
||||||
return Literator(tokens...)
|
return Literator(tokens...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpHeaderBlock(groups []string, lexer Lexer) Iterator {
|
func httpHeaderBlock(groups []string, lexer Lexer) Iterator {
|
||||||
@ -66,7 +65,7 @@ func httpBodyContentTypeLexer(lexer Lexer) Lexer { return &httpBodyContentTyper{
|
|||||||
|
|
||||||
type httpBodyContentTyper struct{ Lexer }
|
type httpBodyContentTyper struct{ Lexer }
|
||||||
|
|
||||||
func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
|
func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit
|
||||||
var contentType string
|
var contentType string
|
||||||
var isContentType bool
|
var isContentType bool
|
||||||
var subIterator Iterator
|
var subIterator Iterator
|
||||||
@ -123,9 +122,7 @@ func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (
|
|||||||
return EOF
|
return EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return token
|
return token
|
||||||
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
54
vendor/github.com/alecthomas/chroma/lexers/hlb.go
generated
vendored
Normal file
54
vendor/github.com/alecthomas/chroma/lexers/hlb.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package lexers
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HLB lexer.
|
||||||
|
var HLB = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "HLB",
|
||||||
|
Aliases: []string{"hlb"},
|
||||||
|
Filenames: []string{"*.hlb"},
|
||||||
|
MimeTypes: []string{},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
{`(#.*)`, ByGroups(CommentSingle), nil},
|
||||||
|
{`((\b(0(b|B|o|O|x|X)[a-fA-F0-9]+)\b)|(\b(0|[1-9][0-9]*)\b))`, ByGroups(LiteralNumber), nil},
|
||||||
|
{`((\b(true|false)\b))`, ByGroups(NameBuiltin), nil},
|
||||||
|
{`(\bstring\b|\bint\b|\bbool\b|\bfs\b|\boption\b)`, ByGroups(KeywordType), nil},
|
||||||
|
{`(\b[a-zA-Z_][a-zA-Z0-9]*\b)(\()`, ByGroups(NameFunction, Punctuation), Push("params")},
|
||||||
|
{`(\{)`, ByGroups(Punctuation), Push("block")},
|
||||||
|
{`(\n|\r|\r\n)`, Text, nil},
|
||||||
|
{`.`, Text, nil},
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
{`"`, LiteralString, Pop(1)},
|
||||||
|
{`\\"`, LiteralString, nil},
|
||||||
|
{`[^\\"]+`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"block": {
|
||||||
|
{`(\})`, ByGroups(Punctuation), Pop(1)},
|
||||||
|
{`(#.*)`, ByGroups(CommentSingle), nil},
|
||||||
|
{`((\b(0(b|B|o|O|x|X)[a-fA-F0-9]+)\b)|(\b(0|[1-9][0-9]*)\b))`, ByGroups(LiteralNumber), nil},
|
||||||
|
{`((\b(true|false)\b))`, ByGroups(KeywordConstant), nil},
|
||||||
|
{`"`, LiteralString, Push("string")},
|
||||||
|
{`(with)`, ByGroups(KeywordReserved), nil},
|
||||||
|
{`(as)([\t ]+)(\b[a-zA-Z_][a-zA-Z0-9]*\b)`, ByGroups(KeywordReserved, Text, NameFunction), nil},
|
||||||
|
{`(\bstring\b|\bint\b|\bbool\b|\bfs\b|\boption\b)([\t ]+)(\{)`, ByGroups(KeywordType, Text, Punctuation), Push("block")},
|
||||||
|
{`(?!\b(?:scratch|image|resolve|http|checksum|chmod|filename|git|keepGitDir|local|includePatterns|excludePatterns|followPaths|generate|frontendInput|shell|run|readonlyRootfs|env|dir|user|network|security|host|ssh|secret|mount|target|localPath|uid|gid|mode|readonly|tmpfs|sourcePath|cache|mkdir|createParents|chown|createdTime|mkfile|rm|allowNotFound|allowWildcards|copy|followSymlinks|contentsOnly|unpack|createDestPath)\b)(\b[a-zA-Z_][a-zA-Z0-9]*\b)`, ByGroups(NameOther), nil},
|
||||||
|
{`(\n|\r|\r\n)`, Text, nil},
|
||||||
|
{`.`, Text, nil},
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
{`(\))`, ByGroups(Punctuation), Pop(1)},
|
||||||
|
{`(variadic)`, ByGroups(Keyword), nil},
|
||||||
|
{`(\bstring\b|\bint\b|\bbool\b|\bfs\b|\boption\b)`, ByGroups(KeywordType), nil},
|
||||||
|
{`(\b[a-zA-Z_][a-zA-Z0-9]*\b)`, ByGroups(NameOther), nil},
|
||||||
|
{`(\n|\r|\r\n)`, Text, nil},
|
||||||
|
{`.`, Text, nil},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
2
vendor/github.com/alecthomas/chroma/lexers/i/ini.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/i/ini.go
generated
vendored
@ -10,7 +10,7 @@ var Ini = internal.Register(MustNewLexer(
|
|||||||
&Config{
|
&Config{
|
||||||
Name: "INI",
|
Name: "INI",
|
||||||
Aliases: []string{"ini", "cfg", "dosini"},
|
Aliases: []string{"ini", "cfg", "dosini"},
|
||||||
Filenames: []string{"*.ini", "*.cfg", "*.inf", ".gitconfig"},
|
Filenames: []string{"*.ini", "*.cfg", "*.inf", ".gitconfig", ".editorconfig"},
|
||||||
MimeTypes: []string{"text/x-ini", "text/inf"},
|
MimeTypes: []string{"text/x-ini", "text/inf"},
|
||||||
},
|
},
|
||||||
Rules{
|
Rules{
|
||||||
|
12
vendor/github.com/alecthomas/chroma/lexers/internal/api.go
generated
vendored
12
vendor/github.com/alecthomas/chroma/lexers/internal/api.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
// Package internal contains common API functions and structures shared between lexer packages.
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -36,19 +37,20 @@ func Names(withAliases bool) []string {
|
|||||||
|
|
||||||
// Get a Lexer by name, alias or file extension.
|
// Get a Lexer by name, alias or file extension.
|
||||||
func Get(name string) chroma.Lexer {
|
func Get(name string) chroma.Lexer {
|
||||||
candidates := chroma.PrioritisedLexers{}
|
|
||||||
if lexer := Registry.byName[name]; lexer != nil {
|
if lexer := Registry.byName[name]; lexer != nil {
|
||||||
candidates = append(candidates, lexer)
|
return lexer
|
||||||
}
|
}
|
||||||
if lexer := Registry.byAlias[name]; lexer != nil {
|
if lexer := Registry.byAlias[name]; lexer != nil {
|
||||||
candidates = append(candidates, lexer)
|
return lexer
|
||||||
}
|
}
|
||||||
if lexer := Registry.byName[strings.ToLower(name)]; lexer != nil {
|
if lexer := Registry.byName[strings.ToLower(name)]; lexer != nil {
|
||||||
candidates = append(candidates, lexer)
|
return lexer
|
||||||
}
|
}
|
||||||
if lexer := Registry.byAlias[strings.ToLower(name)]; lexer != nil {
|
if lexer := Registry.byAlias[strings.ToLower(name)]; lexer != nil {
|
||||||
candidates = append(candidates, lexer)
|
return lexer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
candidates := chroma.PrioritisedLexers{}
|
||||||
// Try file extension.
|
// Try file extension.
|
||||||
if lexer := Match("filename." + name); lexer != nil {
|
if lexer := Match("filename." + name); lexer != nil {
|
||||||
candidates = append(candidates, lexer)
|
candidates = append(candidates, lexer)
|
||||||
|
73
vendor/github.com/alecthomas/chroma/lexers/j/j.go
generated
vendored
Normal file
73
vendor/github.com/alecthomas/chroma/lexers/j/j.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package j
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// J lexer.
|
||||||
|
var J = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "J",
|
||||||
|
Aliases: []string{"j"},
|
||||||
|
Filenames: []string{"*.ijs"},
|
||||||
|
MimeTypes: []string{"text/x-j"},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
{`#!.*$`, CommentPreproc, nil},
|
||||||
|
{`NB\..*`, CommentSingle, nil},
|
||||||
|
{`\n+\s*Note`, CommentMultiline, Push("comment")},
|
||||||
|
{`\s*Note.*`, CommentSingle, nil},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
{`'`, LiteralString, Push("singlequote")},
|
||||||
|
{`0\s+:\s*0|noun\s+define\s*$`, NameEntity, Push("nounDefinition")},
|
||||||
|
{`(([1-4]|13)\s+:\s*0|(adverb|conjunction|dyad|monad|verb)\s+define)\b`, NameFunction, Push("explicitDefinition")},
|
||||||
|
{Words(``, `\b[a-zA-Z]\w*\.`, `for_`, `goto_`, `label_`), NameLabel, nil},
|
||||||
|
{Words(``, `\.`, `assert`, `break`, `case`, `catch`, `catchd`, `catcht`, `continue`, `do`, `else`, `elseif`, `end`, `fcase`, `for`, `if`, `return`, `select`, `throw`, `try`, `while`, `whilst`), NameLabel, nil},
|
||||||
|
{`\b[a-zA-Z]\w*`, NameVariable, nil},
|
||||||
|
{Words(``, ``, `ARGV`, `CR`, `CRLF`, `DEL`, `Debug`, `EAV`, `EMPTY`, `FF`, `JVERSION`, `LF`, `LF2`, `Note`, `TAB`, `alpha17`, `alpha27`, `apply`, `bind`, `boxopen`, `boxxopen`, `bx`, `clear`, `cutLF`, `cutopen`, `datatype`, `def`, `dfh`, `drop`, `each`, `echo`, `empty`, `erase`, `every`, `evtloop`, `exit`, `expand`, `fetch`, `file2url`, `fixdotdot`, `fliprgb`, `getargs`, `getenv`, `hfd`, `inv`, `inverse`, `iospath`, `isatty`, `isutf8`, `items`, `leaf`, `list`, `nameclass`, `namelist`, `names`, `nc`, `nl`, `on`, `pick`, `rows`, `script`, `scriptd`, `sign`, `sminfo`, `smoutput`, `sort`, `split`, `stderr`, `stdin`, `stdout`, `table`, `take`, `timespacex`, `timex`, `tmoutput`, `toCRLF`, `toHOST`, `toJ`, `tolower`, `toupper`, `type`, `ucp`, `ucpcount`, `usleep`, `utf8`, `uucp`), NameFunction, nil},
|
||||||
|
{`=[.:]`, Operator, nil},
|
||||||
|
{"[-=+*#$%@!~`^&\";:.,<>{}\\[\\]\\\\|/]", Operator, nil},
|
||||||
|
{`[abCdDeEfHiIjLMoprtT]\.`, KeywordReserved, nil},
|
||||||
|
{`[aDiLpqsStux]\:`, KeywordReserved, nil},
|
||||||
|
{`(_[0-9])\:`, KeywordConstant, nil},
|
||||||
|
{`\(`, Punctuation, Push("parentheses")},
|
||||||
|
Include("numbers"),
|
||||||
|
},
|
||||||
|
"comment": {
|
||||||
|
{`[^)]`, CommentMultiline, nil},
|
||||||
|
{`^\)`, CommentMultiline, Pop(1)},
|
||||||
|
{`[)]`, CommentMultiline, nil},
|
||||||
|
},
|
||||||
|
"explicitDefinition": {
|
||||||
|
{`\b[nmuvxy]\b`, NameDecorator, nil},
|
||||||
|
Include("root"),
|
||||||
|
{`[^)]`, Name, nil},
|
||||||
|
{`^\)`, NameLabel, Pop(1)},
|
||||||
|
{`[)]`, Name, nil},
|
||||||
|
},
|
||||||
|
"numbers": {
|
||||||
|
{`\b_{1,2}\b`, LiteralNumber, nil},
|
||||||
|
{`_?\d+(\.\d+)?(\s*[ejr]\s*)_?\d+(\.?=\d+)?`, LiteralNumber, nil},
|
||||||
|
{`_?\d+\.(?=\d+)`, LiteralNumberFloat, nil},
|
||||||
|
{`_?\d+x`, LiteralNumberIntegerLong, nil},
|
||||||
|
{`_?\d+`, LiteralNumberInteger, nil},
|
||||||
|
},
|
||||||
|
"nounDefinition": {
|
||||||
|
{`[^)]`, LiteralString, nil},
|
||||||
|
{`^\)`, NameLabel, Pop(1)},
|
||||||
|
{`[)]`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"parentheses": {
|
||||||
|
{`\)`, Punctuation, Pop(1)},
|
||||||
|
Include("explicitDefinition"),
|
||||||
|
Include("root"),
|
||||||
|
},
|
||||||
|
"singlequote": {
|
||||||
|
{`[^']`, LiteralString, nil},
|
||||||
|
{`''`, LiteralString, nil},
|
||||||
|
{`'`, LiteralString, Pop(1)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
7
vendor/github.com/alecthomas/chroma/lexers/j/java.go
generated
vendored
7
vendor/github.com/alecthomas/chroma/lexers/j/java.go
generated
vendored
@ -20,7 +20,7 @@ var Java = internal.Register(MustNewLexer(
|
|||||||
{`//.*?\n`, CommentSingle, nil},
|
{`//.*?\n`, CommentSingle, nil},
|
||||||
{`/\*.*?\*/`, CommentMultiline, nil},
|
{`/\*.*?\*/`, CommentMultiline, nil},
|
||||||
{`(assert|break|case|catch|continue|default|do|else|finally|for|if|goto|instanceof|new|return|switch|this|throw|try|while)\b`, Keyword, nil},
|
{`(assert|break|case|catch|continue|default|do|else|finally|for|if|goto|instanceof|new|return|switch|this|throw|try|while)\b`, Keyword, nil},
|
||||||
{`((?:(?:[^\W\d]|\$)[\w.\[\]$<>]*\s+)+?)((?:[^\W\d]|\$)[\w$]*)(\s*)`, ByGroups(UsingSelf("root"), NameFunction, Text, Operator), nil},
|
{`((?:(?:[^\W\d]|\$)[\w.\[\]$<>]*\s+)+?)((?:[^\W\d]|\$)[\w$]*)(\s*)(\()`, ByGroups(UsingSelf("root"), NameFunction, Text, Operator), nil},
|
||||||
{`@[^\W\d][\w.]*`, NameDecorator, nil},
|
{`@[^\W\d][\w.]*`, NameDecorator, nil},
|
||||||
{`(abstract|const|enum|extends|final|implements|native|private|protected|public|static|strictfp|super|synchronized|throws|transient|volatile)\b`, KeywordDeclaration, nil},
|
{`(abstract|const|enum|extends|final|implements|native|private|protected|public|static|strictfp|super|synchronized|throws|transient|volatile)\b`, KeywordDeclaration, nil},
|
||||||
{`(boolean|byte|char|double|float|int|long|short|void)\b`, KeywordType, nil},
|
{`(boolean|byte|char|double|float|int|long|short|void)\b`, KeywordType, nil},
|
||||||
@ -30,7 +30,7 @@ var Java = internal.Register(MustNewLexer(
|
|||||||
{`(import(?:\s+static)?)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
{`(import(?:\s+static)?)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
||||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||||
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
||||||
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Punctuation, NameAttribute), nil},
|
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
|
||||||
{`^\s*([^\W\d]|\$)[\w$]*:`, NameLabel, nil},
|
{`^\s*([^\W\d]|\$)[\w$]*:`, NameLabel, nil},
|
||||||
{`([^\W\d]|\$)[\w$]*`, Name, nil},
|
{`([^\W\d]|\$)[\w$]*`, Name, nil},
|
||||||
{`([0-9][0-9_]*\.([0-9][0-9_]*)?|\.[0-9][0-9_]*)([eE][+\-]?[0-9][0-9_]*)?[fFdD]?|[0-9][eE][+\-]?[0-9][0-9_]*[fFdD]?|[0-9]([eE][+\-]?[0-9][0-9_]*)?[fFdD]|0[xX]([0-9a-fA-F][0-9a-fA-F_]*\.?|([0-9a-fA-F][0-9a-fA-F_]*)?\.[0-9a-fA-F][0-9a-fA-F_]*)[pP][+\-]?[0-9][0-9_]*[fFdD]?`, LiteralNumberFloat, nil},
|
{`([0-9][0-9_]*\.([0-9][0-9_]*)?|\.[0-9][0-9_]*)([eE][+\-]?[0-9][0-9_]*)?[fFdD]?|[0-9][eE][+\-]?[0-9][0-9_]*[fFdD]?|[0-9]([eE][+\-]?[0-9][0-9_]*)?[fFdD]|0[xX]([0-9a-fA-F][0-9a-fA-F_]*\.?|([0-9a-fA-F][0-9a-fA-F_]*)?\.[0-9a-fA-F][0-9a-fA-F_]*)[pP][+\-]?[0-9][0-9_]*[fFdD]?`, LiteralNumberFloat, nil},
|
||||||
@ -38,8 +38,7 @@ var Java = internal.Register(MustNewLexer(
|
|||||||
{`0[bB][01][01_]*[lL]?`, LiteralNumberBin, nil},
|
{`0[bB][01][01_]*[lL]?`, LiteralNumberBin, nil},
|
||||||
{`0[0-7_]+[lL]?`, LiteralNumberOct, nil},
|
{`0[0-7_]+[lL]?`, LiteralNumberOct, nil},
|
||||||
{`0|[1-9][0-9_]*[lL]?`, LiteralNumberInteger, nil},
|
{`0|[1-9][0-9_]*[lL]?`, LiteralNumberInteger, nil},
|
||||||
{`[~^*!%&<>|+=:/?-]`, Operator, nil},
|
{`[~^*!%&\[\](){}<>|+=:;,./?-]`, Operator, nil},
|
||||||
{`[\[\](){};,.]`, Punctuation, nil},
|
|
||||||
{`\n`, Text, nil},
|
{`\n`, Text, nil},
|
||||||
},
|
},
|
||||||
"class": {
|
"class": {
|
||||||
|
2
vendor/github.com/alecthomas/chroma/lexers/j/javascript.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/j/javascript.go
generated
vendored
File diff suppressed because one or more lines are too long
7
vendor/github.com/alecthomas/chroma/lexers/j/jsx.go
generated
vendored
7
vendor/github.com/alecthomas/chroma/lexers/j/jsx.go
generated
vendored
File diff suppressed because one or more lines are too long
59
vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go
generated
vendored
59
vendor/github.com/alecthomas/chroma/lexers/k/kotlin.go
generated
vendored
@ -24,32 +24,71 @@ var Kotlin = internal.Register(MustNewLexer(
|
|||||||
{`//[^\n]*\n?`, CommentSingle, nil},
|
{`//[^\n]*\n?`, CommentSingle, nil},
|
||||||
{`/[*].*?[*]/`, CommentMultiline, nil},
|
{`/[*].*?[*]/`, CommentMultiline, nil},
|
||||||
{`\n`, Text, nil},
|
{`\n`, Text, nil},
|
||||||
{`::|!!|\?[:.]`, Operator, nil},
|
{`!==|!in|!is|===`, Operator, nil},
|
||||||
{`[~!%^&*()+=|\[\]:;,.<>/?-]`, Punctuation, nil},
|
{`%=|&&|\*=|\+\+|\+=|--|-=|->|\.\.|\/=|::|<=|==|>=|!!|!=|\|\||\?[:.]`, Operator, nil},
|
||||||
|
{`[~!%^&*()+=|\[\]:;,.<>\/?-]`, Punctuation, nil},
|
||||||
{`[{}]`, Punctuation, nil},
|
{`[{}]`, Punctuation, nil},
|
||||||
{`"""[^"]*"""`, LiteralString, nil},
|
{`"""`, LiteralString, Push("rawstring")},
|
||||||
{`"(\\\\|\\"|[^"\n])*["\n]`, LiteralString, nil},
|
{`"`, LiteralStringDouble, Push("string")},
|
||||||
|
{`(')(\\u[0-9a-fA-F]{4})(')`, ByGroups(LiteralStringChar, LiteralStringEscape, LiteralStringChar), nil},
|
||||||
{`'\\.'|'[^\\]'`, LiteralStringChar, nil},
|
{`'\\.'|'[^\\]'`, LiteralStringChar, nil},
|
||||||
{`0[xX][0-9a-fA-F]+[Uu]?[Ll]?|[0-9]+(\.[0-9]*)?([eE][+-][0-9]+)?[fF]?[Uu]?[Ll]?`, LiteralNumber, nil},
|
{`0[xX][0-9a-fA-F]+[Uu]?[Ll]?|[0-9]+(\.[0-9]*)?([eE][+-][0-9]+)?[fF]?[Uu]?[Ll]?`, LiteralNumber, nil},
|
||||||
{`(companion)(\s+)(object)`, ByGroups(Keyword, Text, Keyword), nil},
|
{`(companion)(\s+)(object)`, ByGroups(Keyword, Text, Keyword), nil},
|
||||||
{`(class|interface|object)(\s+)`, ByGroups(Keyword, Text), Push("class")},
|
{`(class|interface|object)(\s+)`, ByGroups(Keyword, Text), Push("class")},
|
||||||
{`(package|import)(\s+)`, ByGroups(Keyword, Text), Push("package")},
|
{`(package|import)(\s+)`, ByGroups(Keyword, Text), Push("package")},
|
||||||
{`(val|var)(\s+)`, ByGroups(Keyword, Text), Push("property")},
|
{`(val|var)(\s+)`, ByGroups(Keyword, Text), Push("property")},
|
||||||
{`(fun)(\s+)(<[^>]*>\s+)?`, ByGroups(Keyword, Text, Text), Push("function")},
|
{`(fun)(\s+)`, ByGroups(Keyword, Text), Push("function")},
|
||||||
{`(abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|false|final|finally|for|fun|get|if|import|in|infix|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|true|try|val|var|vararg|when|where|while)\b`, Keyword, nil},
|
{`(abstract|actual|annotation|as|as\?|break|by|catch|class|companion|const|constructor|continue|crossinline|data|delegate|do|dynamic|else|enum|expect|external|false|field|file|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|it|lateinit|noinline|null|object|open|operator|out|override|package|param|private|property|protected|public|receiver|reified|return|sealed|set|setparam|super|suspend|tailrec|this|throw|true|try|typealias|typeof|val|var|vararg|when|where|while)\b`, Keyword, nil},
|
||||||
{"(@?[" + kotlinIdentifier + "]*`)", Name, nil},
|
{`@[` + kotlinIdentifier + `]+`, NameDecorator, nil},
|
||||||
|
{`[` + kotlinIdentifier + `]+`, Name, nil},
|
||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
{`\S+`, NameNamespace, Pop(1)},
|
{`\S+`, NameNamespace, Pop(1)},
|
||||||
},
|
},
|
||||||
"class": {
|
"class": {
|
||||||
{"(@?[" + kotlinIdentifier + "]*`)", NameClass, Pop(1)},
|
// \x60 is the back tick character (`)
|
||||||
|
{`\x60[^\x60]+?\x60`, NameClass, Pop(1)},
|
||||||
|
{`[` + kotlinIdentifier + `]+`, NameClass, Pop(1)},
|
||||||
},
|
},
|
||||||
"property": {
|
"property": {
|
||||||
{"(@?[" + kotlinIdentifier + " ]*`)", NameProperty, Pop(1)},
|
{`\x60[^\x60]+?\x60`, NameProperty, Pop(1)},
|
||||||
|
{`[` + kotlinIdentifier + `]+`, NameProperty, Pop(1)},
|
||||||
|
},
|
||||||
|
"generics-specification": {
|
||||||
|
{`<`, Punctuation, Push("generics-specification")}, // required for generics inside generics e.g. <T : List<Int> >
|
||||||
|
{`>`, Punctuation, Pop(1)},
|
||||||
|
{`[,:*?]`, Punctuation, nil},
|
||||||
|
{`(in|out|reified)`, Keyword, nil},
|
||||||
|
{`\x60[^\x60]+?\x60`, NameClass, nil},
|
||||||
|
{`[` + kotlinIdentifier + `]+`, NameClass, nil},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
},
|
},
|
||||||
"function": {
|
"function": {
|
||||||
{"(@?[" + kotlinIdentifier + " ]*`)", NameFunction, Pop(1)},
|
{`<`, Punctuation, Push("generics-specification")},
|
||||||
|
{`\x60[^\x60]+?\x60`, NameFunction, Pop(1)},
|
||||||
|
{`[` + kotlinIdentifier + `]+`, NameFunction, Pop(1)},
|
||||||
|
{`\s+`, Text, nil},
|
||||||
|
},
|
||||||
|
"rawstring": {
|
||||||
|
// raw strings don't allow character escaping
|
||||||
|
{`"""`, LiteralString, Pop(1)},
|
||||||
|
{`(?:[^$"]+|\"{1,2}[^"])+`, LiteralString, nil},
|
||||||
|
Include("string-interpol"),
|
||||||
|
// remaining dollar signs are just a string
|
||||||
|
{`\$`, LiteralString, nil},
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
{`\\[tbnr'"\\\$]`, LiteralStringEscape, nil},
|
||||||
|
{`\\u[0-9a-fA-F]{4}`, LiteralStringEscape, nil},
|
||||||
|
{`"`, LiteralStringDouble, Pop(1)},
|
||||||
|
Include("string-interpol"),
|
||||||
|
{`[^\n\\"$]+`, LiteralStringDouble, nil},
|
||||||
|
// remaining dollar signs are just a string
|
||||||
|
{`\$`, LiteralStringDouble, nil},
|
||||||
|
},
|
||||||
|
"string-interpol": {
|
||||||
|
{`\$[` + kotlinIdentifier + `]+`, LiteralStringInterpol, nil},
|
||||||
|
{`\${[^}\n]*}`, LiteralStringInterpol, nil},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
1
vendor/github.com/alecthomas/chroma/lexers/lexers.go
generated
vendored
1
vendor/github.com/alecthomas/chroma/lexers/lexers.go
generated
vendored
@ -32,6 +32,7 @@ import (
|
|||||||
_ "github.com/alecthomas/chroma/lexers/w"
|
_ "github.com/alecthomas/chroma/lexers/w"
|
||||||
_ "github.com/alecthomas/chroma/lexers/x"
|
_ "github.com/alecthomas/chroma/lexers/x"
|
||||||
_ "github.com/alecthomas/chroma/lexers/y"
|
_ "github.com/alecthomas/chroma/lexers/y"
|
||||||
|
_ "github.com/alecthomas/chroma/lexers/z"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry of Lexers.
|
// Registry of Lexers.
|
||||||
|
9
vendor/github.com/alecthomas/chroma/lexers/m/markdown.go
generated
vendored
9
vendor/github.com/alecthomas/chroma/lexers/m/markdown.go
generated
vendored
@ -2,11 +2,12 @@ package m
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/alecthomas/chroma" // nolint
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/h"
|
||||||
"github.com/alecthomas/chroma/lexers/internal"
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Markdown lexer.
|
// Markdown lexer.
|
||||||
var Markdown = internal.Register(MustNewLexer(
|
var Markdown = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
|
||||||
&Config{
|
&Config{
|
||||||
Name: "markdown",
|
Name: "markdown",
|
||||||
Aliases: []string{"md", "mkd"},
|
Aliases: []string{"md", "mkd"},
|
||||||
@ -40,8 +41,8 @@ var Markdown = internal.Register(MustNewLexer(
|
|||||||
{"`[^`]+`", LiteralStringBacktick, nil},
|
{"`[^`]+`", LiteralStringBacktick, nil},
|
||||||
{`[@#][\w/:]+`, NameEntity, nil},
|
{`[@#][\w/:]+`, NameEntity, nil},
|
||||||
{`(!?\[)([^]]+)(\])(\()([^)]+)(\))`, ByGroups(Text, NameTag, Text, Text, NameAttribute, Text), nil},
|
{`(!?\[)([^]]+)(\])(\()([^)]+)(\))`, ByGroups(Text, NameTag, Text, Text, NameAttribute, Text), nil},
|
||||||
{`[^\\\s]+`, Text, nil},
|
{`[^\\\s]+`, Other, nil},
|
||||||
{`.|\n`, Text, nil},
|
{`.|\n`, Other, nil},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
))
|
)))
|
||||||
|
43
vendor/github.com/alecthomas/chroma/lexers/m/mlir.go
generated
vendored
Normal file
43
vendor/github.com/alecthomas/chroma/lexers/m/mlir.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package m
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/alecthomas/chroma" // nolint
|
||||||
|
"github.com/alecthomas/chroma/lexers/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MLIR lexer.
|
||||||
|
var Mlir = internal.Register(MustNewLexer(
|
||||||
|
&Config{
|
||||||
|
Name: "MLIR",
|
||||||
|
Aliases: []string{"mlir"},
|
||||||
|
Filenames: []string{"*.mlir"},
|
||||||
|
MimeTypes: []string{"text/x-mlir"},
|
||||||
|
},
|
||||||
|
Rules{
|
||||||
|
"root": {
|
||||||
|
Include("whitespace"),
|
||||||
|
{`c?"[^"]*?"`, LiteralString, nil},
|
||||||
|
{`\^([-a-zA-Z$._][\w\-$.0-9]*)\s*`, NameLabel, nil},
|
||||||
|
{`([\w\d_$.]+)\s*=`, NameLabel, nil},
|
||||||
|
Include("keyword"),
|
||||||
|
{`->`, Punctuation, nil},
|
||||||
|
{`@([\w_][\w\d_$.]*)`, NameFunction, nil},
|
||||||
|
{`[%#][\w\d_$.]+`, NameVariable, nil},
|
||||||
|
{`([1-9?][\d?]*\s*x)+`, LiteralNumber, nil},
|
||||||
|
{`0[xX][a-fA-F0-9]+`, LiteralNumber, nil},
|
||||||
|
{`-?\d+(?:[.]\d+)?(?:[eE][-+]?\d+(?:[.]\d+)?)?`, LiteralNumber, nil},
|
||||||
|
{`[=<>{}\[\]()*.,!:]|x\b`, Punctuation, nil},
|
||||||
|
{`[\w\d]+`, Text, nil},
|
||||||
|
},
|
||||||
|
"whitespace": {
|
||||||
|
{`(\n|\s)+`, Text, nil},
|
||||||
|
{`//.*?\n`, Comment, nil},
|
||||||
|
},
|
||||||
|
"keyword": {
|
||||||
|
{Words(``, ``, `constant`, `return`), KeywordType, nil},
|
||||||
|
{Words(``, ``, `func`, `loc`, `memref`, `tensor`, `vector`), KeywordType, nil},
|
||||||
|
{`bf16|f16|f32|f64|index`, Keyword, nil},
|
||||||
|
{`i[1-9]\d*`, Keyword, nil},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
2
vendor/github.com/alecthomas/chroma/lexers/m/mysql.go
generated
vendored
2
vendor/github.com/alecthomas/chroma/lexers/m/mysql.go
generated
vendored
@ -26,7 +26,7 @@ var MySQL = internal.Register(MustNewLexer(
|
|||||||
{`((?:_[a-z0-9]+)?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("double-string")},
|
{`((?:_[a-z0-9]+)?)(")`, ByGroups(LiteralStringAffix, LiteralStringDouble), Push("double-string")},
|
||||||
{"[+*/<>=~!@#%^&|`?-]", Operator, nil},
|
{"[+*/<>=~!@#%^&|`?-]", Operator, nil},
|
||||||
{`\b(tinyint|smallint|mediumint|int|integer|bigint|date|datetime|time|bit|bool|tinytext|mediumtext|longtext|text|tinyblob|mediumblob|longblob|blob|float|double|double\s+precision|real|numeric|dec|decimal|timestamp|year|char|varchar|varbinary|varcharacter|enum|set)(\b\s*)(\()?`, ByGroups(KeywordType, Text, Punctuation), nil},
|
{`\b(tinyint|smallint|mediumint|int|integer|bigint|date|datetime|time|bit|bool|tinytext|mediumtext|longtext|text|tinyblob|mediumblob|longblob|blob|float|double|double\s+precision|real|numeric|dec|decimal|timestamp|year|char|varchar|varbinary|varcharacter|enum|set)(\b\s*)(\()?`, ByGroups(KeywordType, Text, Punctuation), nil},
|
||||||
{`\b(add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|fetch|flush|float|float4|float8|for|force|foreign|from|fulltext|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|lines|load|localtime|localtimestamp|lock|long|loop|low_priority|match|minute_microsecond|minute_second|mod|modifies|natural|no_write_to_binlog|not|numeric|on|optimize|option|optionally|or|order|out|outer|outfile|precision|primary|procedure|purge|raid0|read|reads|real|references|regexp|release|rename|repeat|replace|require|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|smallint|soname|spatial|specific|sql|sql_big_result|sql_calc_found_rows|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|starting|straight_join|table|terminated|then|to|trailing|trigger|undo|union|unique|unlock|unsigned|update|usage|use|using|utc_date|utc_time|utc_timestamp|values|varying|when|where|while|with|write|x509|xor|year_month|zerofill)\b`, Keyword, nil},
|
{`\b(add|all|alter|analyze|and|as|asc|asensitive|before|between|bigint|binary|blob|both|by|call|cascade|case|change|char|character|check|collate|column|condition|constraint|continue|convert|create|cross|current_date|current_time|current_timestamp|current_user|cursor|database|databases|day_hour|day_microsecond|day_minute|day_second|dec|decimal|declare|default|delayed|delete|desc|describe|deterministic|distinct|distinctrow|div|double|drop|dual|each|else|elseif|enclosed|escaped|exists|exit|explain|fetch|flush|float|float4|float8|for|force|foreign|from|fulltext|grant|group|having|high_priority|hour_microsecond|hour_minute|hour_second|identified|if|ignore|in|index|infile|inner|inout|insensitive|insert|int|int1|int2|int3|int4|int8|integer|interval|into|is|iterate|join|key|keys|kill|leading|leave|left|like|limit|lines|load|localtime|localtimestamp|lock|long|loop|low_priority|match|minute_microsecond|minute_second|mod|modifies|natural|no_write_to_binlog|not|numeric|on|optimize|option|optionally|or|order|out|outer|outfile|precision|primary|privileges|procedure|purge|raid0|read|reads|real|references|regexp|release|rename|repeat|replace|require|restrict|return|revoke|right|rlike|schema|schemas|second_microsecond|select|sensitive|separator|set|show|smallint|soname|spatial|specific|sql|sql_big_result|sql_calc_found_rows|sql_small_result|sqlexception|sqlstate|sqlwarning|ssl|starting|straight_join|table|terminated|then|to|trailing|trigger|undo|union|unique|unlock|unsigned|update|usage|use|user|using|utc_date|utc_time|utc_timestamp|values|varying|when|where|while|with|write|x509|xor|year_month|zerofill)\b`, Keyword, nil},
|
||||||
{`\b(auto_increment|engine|charset|tables)\b`, KeywordPseudo, nil},
|
{`\b(auto_increment|engine|charset|tables)\b`, KeywordPseudo, nil},
|
||||||
{`(true|false|null)`, NameConstant, nil},
|
{`(true|false|null)`, NameConstant, nil},
|
||||||
{`([a-z_]\w*)(\s*)(\()`, ByGroups(NameFunction, Text, Punctuation), nil},
|
{`([a-z_]\w*)(\s*)(\()`, ByGroups(NameFunction, Text, Punctuation), nil},
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user