de-inline go-termd
This commit is contained in:
parent
4592aaf63d
commit
daf02ff3ec
6 changed files with 4 additions and 368 deletions
8
go.mod
8
go.mod
|
|
@ -4,23 +4,17 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.0.4
|
||||
github.com/alecthomas/chroma v0.6.8
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/kr/text v0.1.0
|
||||
github.com/mattn/go-colorable v0.1.2
|
||||
github.com/mattn/go-isatty v0.0.9
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/go-wordwrap v1.0.0
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/russross/blackfriday/v2 v2.0.1
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/spf13/cobra v0.0.5
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/tj/go-css v0.0.0-20191108133013-220a796d1705
|
||||
github.com/vilmibm/go-termd v0.0.4
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5
|
||||
gopkg.in/yaml.v3 v3.0.0-20191010095647-fc94e3f71652
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -110,6 +110,8 @@ github.com/tj/go-css v0.0.0-20191108133013-220a796d1705/go.mod h1:e+JPLQ9wyQCgRn
|
|||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/vilmibm/go-termd v0.0.4 h1:uCmDUZ3qZUblTN/D5Hvl+g1rTJj/HW746JQFWidqAyk=
|
||||
github.com/vilmibm/go-termd v0.0.4/go.mod h1:ys+dRO6wlM3el0vPJmYBkhOPPozViBgDXHOEn1x5Vsc=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
// This package is sourced from https://github.com/tj/go-termd under the terms of the MIT license.
|
||||
// It was inlined to work around some dependency issues.
|
||||
package markdown
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/chroma"
|
||||
"github.com/alecthomas/chroma/lexers"
|
||||
)
|
||||
|
||||
// SyntaxHighlighter is the interface used to highlight blocks of code.
|
||||
type SyntaxHighlighter interface {
|
||||
Token(chroma.Token) string
|
||||
}
|
||||
|
||||
// highlight returns highlighted code, or the input text on error.
|
||||
func highlight(source, lang string, highlight SyntaxHighlighter) string {
|
||||
l := lexers.Get(lang)
|
||||
if l == nil {
|
||||
return source
|
||||
}
|
||||
|
||||
l = chroma.Coalesce(l)
|
||||
|
||||
it, err := l.Tokenise(nil, source)
|
||||
if err != nil {
|
||||
return source
|
||||
}
|
||||
|
||||
var w strings.Builder
|
||||
for _, t := range it.Tokens() {
|
||||
w.WriteString(highlight.Token(t))
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
// Package markdown provides terminal markdown rendering,
|
||||
// with code block syntax highlighting support.
|
||||
// This package is sourced from https://github.com/tj/go-termd under the terms of the MIT license.
|
||||
// It was inlined to work around some dependency issues.
|
||||
package markdown
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/kr/text"
|
||||
"github.com/mitchellh/go-wordwrap"
|
||||
blackfriday "github.com/russross/blackfriday/v2"
|
||||
)
|
||||
|
||||
// Compiler is the markdown to text compiler. The zero value can be used.
|
||||
type Compiler struct {
|
||||
// Columns is the number of columns to wrap text, defaulting to 90.
|
||||
Columns int
|
||||
|
||||
// Markdown is an optional instance of a blackfriday markdown parser,
|
||||
// defaulting to one with CommonExtensions enabled.
|
||||
Markdown *blackfriday.Markdown
|
||||
|
||||
// SyntaxHighlighter is an optional syntax highlighter for code blocks,
|
||||
// using the low-level SyntaxHighlighter interface, or SyntaxTheme map.
|
||||
SyntaxHighlighter
|
||||
|
||||
inBlockQuote bool
|
||||
inList bool
|
||||
}
|
||||
|
||||
// Compile returns a terminal-styled plain text representation of a markdown string.
|
||||
func (c *Compiler) Compile(s string) string {
|
||||
if c.Markdown == nil {
|
||||
c.Markdown = blackfriday.New(blackfriday.WithExtensions(blackfriday.CommonExtensions))
|
||||
}
|
||||
|
||||
if c.Columns == 0 {
|
||||
c.Columns = 90
|
||||
}
|
||||
|
||||
if c.SyntaxHighlighter == nil {
|
||||
c.SyntaxHighlighter = SyntaxTheme{}
|
||||
}
|
||||
|
||||
n := c.Markdown.Parse([]byte(s))
|
||||
return c.visit(n)
|
||||
}
|
||||
|
||||
// visit returns a compiled node string.
|
||||
func (c *Compiler) visit(n *blackfriday.Node) (s string) {
|
||||
switch n.Type {
|
||||
case blackfriday.Document:
|
||||
s = c.visit(n.FirstChild)
|
||||
case blackfriday.BlockQuote:
|
||||
prev := c.inBlockQuote
|
||||
c.inBlockQuote = true
|
||||
s = c.visit(n.FirstChild)
|
||||
s = fmt.Sprintf("\033[38;5;102m%s\033[m", s)
|
||||
c.inBlockQuote = prev
|
||||
case blackfriday.List:
|
||||
prev := c.inList
|
||||
c.inList = true
|
||||
s = fmt.Sprintf("%s\n", c.visit(n.FirstChild))
|
||||
c.inList = prev
|
||||
case blackfriday.Item:
|
||||
s = fmt.Sprintf(" - %s", c.visit(n.FirstChild))
|
||||
case blackfriday.Paragraph:
|
||||
s = c.visit(n.FirstChild)
|
||||
if c.inList {
|
||||
s += "\n"
|
||||
} else {
|
||||
s = wordwrap.WrapString(s, uint(c.Columns))
|
||||
s = text.Indent(s, " ")
|
||||
s += "\n\n"
|
||||
}
|
||||
case blackfriday.Heading:
|
||||
h := strings.Repeat("#", n.HeadingData.Level)
|
||||
t := c.visit(n.FirstChild)
|
||||
s = fmt.Sprintf("\033[1m%s %s\033[m\n\n", h, t)
|
||||
case blackfriday.HorizontalRule:
|
||||
s = fmt.Sprintf(" %s\n\n", strings.Repeat("─", c.Columns))
|
||||
case blackfriday.Emph:
|
||||
s = c.visit(n.FirstChild)
|
||||
if !c.inBlockQuote {
|
||||
s = fmt.Sprintf("\033[3m%s\033[m", s)
|
||||
}
|
||||
case blackfriday.Strong:
|
||||
s = c.visit(n.FirstChild)
|
||||
if !c.inBlockQuote {
|
||||
s = fmt.Sprintf("\033[1m%s\033[m", s)
|
||||
}
|
||||
case blackfriday.Link:
|
||||
s = c.visit(n.FirstChild)
|
||||
d := string(n.LinkData.Destination)
|
||||
if s != d {
|
||||
s = fmt.Sprintf("%s (%s)", s, d)
|
||||
}
|
||||
case blackfriday.Image:
|
||||
s = string(n.LinkData.Destination)
|
||||
case blackfriday.Text:
|
||||
s = string(n.Literal)
|
||||
case blackfriday.CodeBlock:
|
||||
lang := string(n.CodeBlockData.Info)
|
||||
s = string(n.Literal)
|
||||
s = highlight(s, lang, c.SyntaxHighlighter)
|
||||
s = fmt.Sprintf("%s\n", text.Indent(s, " "))
|
||||
case blackfriday.Code:
|
||||
s = fmt.Sprintf("\033[38;5;102m`%s`\033[m", string(n.Literal))
|
||||
case blackfriday.HTMLSpan:
|
||||
// ignore
|
||||
default:
|
||||
s = fmt.Sprintf("<unhandled: %v>", n)
|
||||
}
|
||||
|
||||
if n.Next != nil {
|
||||
s += c.visit(n.Next)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -1,202 +0,0 @@
|
|||
// This package is sourced from https://github.com/tj/go-termd under the terms of the MIT license.
|
||||
// It was inlined to work around some dependency issues.
|
||||
package markdown
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/alecthomas/chroma"
|
||||
"github.com/aybabtme/rgbterm"
|
||||
"github.com/tj/go-css/csshex"
|
||||
)
|
||||
|
||||
// Style is the configuration used to style a particular token.
|
||||
type Style struct {
|
||||
Color string `json:"color"`
|
||||
Background string `json:"background"`
|
||||
Bold bool `json:"bold"`
|
||||
Faint bool `json:"faint"`
|
||||
Italic bool `json:"italic"`
|
||||
Underline bool `json:"underline"`
|
||||
}
|
||||
|
||||
// apply returns a string with the style applied.
|
||||
func (s Style) apply(v string) string {
|
||||
if s.Bold {
|
||||
v = escape(1, v)
|
||||
}
|
||||
|
||||
if s.Faint {
|
||||
v = escape(2, v)
|
||||
}
|
||||
|
||||
if s.Italic {
|
||||
v = escape(3, v)
|
||||
}
|
||||
|
||||
if s.Underline {
|
||||
v = escape(4, v)
|
||||
}
|
||||
|
||||
if s.Color != "" {
|
||||
v = foreground(v, s.Color)
|
||||
}
|
||||
|
||||
if s.Background != "" {
|
||||
v = background(v, s.Background)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// SyntaxTheme is a map of token names to style configurations.
|
||||
type SyntaxTheme map[string]Style
|
||||
|
||||
// Token implementation.
|
||||
func (c SyntaxTheme) Token(t chroma.Token) string {
|
||||
// specific
|
||||
if s, ok := c.mapped(t.Type, t.Value); ok {
|
||||
return s
|
||||
}
|
||||
|
||||
// sub-category
|
||||
if s, ok := c.mapped(t.Type.SubCategory(), t.Value); ok {
|
||||
return s
|
||||
}
|
||||
|
||||
// category
|
||||
if s, ok := c.mapped(t.Type.Category(), t.Value); ok {
|
||||
return s
|
||||
}
|
||||
|
||||
return t.Value
|
||||
}
|
||||
|
||||
// mapped returns a string mapped to its style, or returns the input string as-is.
|
||||
func (c SyntaxTheme) mapped(t chroma.TokenType, v string) (string, bool) {
|
||||
// check if the key is valid
|
||||
k, ok := themeKeys[t]
|
||||
if !ok {
|
||||
return v, false
|
||||
}
|
||||
|
||||
// check if the style is mapped
|
||||
s, ok := c[k]
|
||||
if !ok {
|
||||
return v, false
|
||||
}
|
||||
|
||||
return s.apply(v), true
|
||||
}
|
||||
|
||||
// escape returns an ansi escape sequence with the given code.
|
||||
func escape(code int, s string) string {
|
||||
return fmt.Sprintf("\033[%dm%s\033[m", code, s)
|
||||
}
|
||||
|
||||
// foreground color.
|
||||
func foreground(s, color string) string {
|
||||
r, g, b, ok := csshex.Parse(color)
|
||||
if !ok {
|
||||
return s
|
||||
}
|
||||
return rgbterm.FgString(s, r, g, b)
|
||||
}
|
||||
|
||||
// background color.
|
||||
func background(s, color string) string {
|
||||
r, g, b, ok := csshex.Parse(color)
|
||||
if !ok {
|
||||
return s
|
||||
}
|
||||
return rgbterm.BgString(s, r, g, b)
|
||||
}
|
||||
|
||||
// themeKeys is the map of token types to names.
|
||||
var themeKeys = map[chroma.TokenType]string{
|
||||
chroma.Keyword: "keyword",
|
||||
chroma.KeywordConstant: "keyword.constant",
|
||||
chroma.KeywordDeclaration: "keyword.declaration",
|
||||
chroma.KeywordNamespace: "keyword.namespace",
|
||||
chroma.KeywordPseudo: "keyword.pseudo",
|
||||
chroma.KeywordReserved: "keyword.reserved",
|
||||
chroma.KeywordType: "keyword.type",
|
||||
chroma.Name: "name",
|
||||
chroma.NameAttribute: "name.attribute",
|
||||
chroma.NameBuiltin: "name.builtin",
|
||||
chroma.NameBuiltinPseudo: "name.builtin.pseudo",
|
||||
chroma.NameClass: "name.class",
|
||||
chroma.NameConstant: "name.constant",
|
||||
chroma.NameDecorator: "name.decorator",
|
||||
chroma.NameEntity: "name.entity",
|
||||
chroma.NameException: "name.exception",
|
||||
chroma.NameFunction: "name.function",
|
||||
chroma.NameFunctionMagic: "name.function.magic",
|
||||
chroma.NameKeyword: "name.keyword",
|
||||
chroma.NameLabel: "name.label",
|
||||
chroma.NameNamespace: "name.namespace",
|
||||
chroma.NameOperator: "name.operator",
|
||||
chroma.NameOther: "name.other",
|
||||
chroma.NamePseudo: "name.pseudo",
|
||||
chroma.NameProperty: "name.property",
|
||||
chroma.NameTag: "name.tag",
|
||||
chroma.NameVariable: "name.variable",
|
||||
chroma.NameVariableAnonymous: "name.variable.anonymous",
|
||||
chroma.NameVariableClass: "name.variable.class",
|
||||
chroma.NameVariableGlobal: "name.variable.global",
|
||||
chroma.NameVariableInstance: "name.variable.instance",
|
||||
chroma.NameVariableMagic: "name.variable.magic",
|
||||
chroma.Literal: "literal",
|
||||
chroma.LiteralDate: "literal.date",
|
||||
chroma.LiteralOther: "literal.other",
|
||||
chroma.LiteralString: "literal.string",
|
||||
chroma.LiteralStringAffix: "literal.string.affix",
|
||||
chroma.LiteralStringAtom: "literal.string.atom",
|
||||
chroma.LiteralStringBacktick: "literal.string.backtick",
|
||||
chroma.LiteralStringBoolean: "literal.string.boolean",
|
||||
chroma.LiteralStringChar: "literal.string.char",
|
||||
chroma.LiteralStringDelimiter: "literal.string.delimiter",
|
||||
chroma.LiteralStringDoc: "literal.string.doc",
|
||||
chroma.LiteralStringDouble: "literal.string.double",
|
||||
chroma.LiteralStringEscape: "literal.string.escape",
|
||||
chroma.LiteralStringHeredoc: "literal.string.heredoc",
|
||||
chroma.LiteralStringInterpol: "literal.string.interpol",
|
||||
chroma.LiteralStringName: "literal.string.name",
|
||||
chroma.LiteralStringOther: "literal.string.other",
|
||||
chroma.LiteralStringRegex: "literal.string.regex",
|
||||
chroma.LiteralStringSingle: "literal.string.single",
|
||||
chroma.LiteralStringSymbol: "literal.string.symbol",
|
||||
chroma.LiteralNumber: "literal.number",
|
||||
chroma.LiteralNumberBin: "literal.number.bin",
|
||||
chroma.LiteralNumberFloat: "literal.number.float",
|
||||
chroma.LiteralNumberHex: "literal.number.hex",
|
||||
chroma.LiteralNumberInteger: "literal.number.integer",
|
||||
chroma.LiteralNumberIntegerLong: "literal.number.integer.long",
|
||||
chroma.LiteralNumberOct: "literal.number.oct",
|
||||
chroma.Operator: "operator",
|
||||
chroma.OperatorWord: "operator.word",
|
||||
chroma.Punctuation: "punctuation",
|
||||
chroma.Comment: "comment",
|
||||
chroma.CommentHashbang: "comment.hashbang",
|
||||
chroma.CommentMultiline: "comment.multiline",
|
||||
chroma.CommentSingle: "comment.single",
|
||||
chroma.CommentSpecial: "comment.special",
|
||||
chroma.CommentPreproc: "comment.preproc",
|
||||
chroma.CommentPreprocFile: "comment.preproc.file",
|
||||
chroma.Generic: "generic",
|
||||
chroma.GenericDeleted: "generic.deleted",
|
||||
chroma.GenericEmph: "generic.emph",
|
||||
chroma.GenericError: "generic.error",
|
||||
chroma.GenericHeading: "generic.heading",
|
||||
chroma.GenericInserted: "generic.inserted",
|
||||
chroma.GenericOutput: "generic.output",
|
||||
chroma.GenericPrompt: "generic.prompt",
|
||||
chroma.GenericStrong: "generic.strong",
|
||||
chroma.GenericSubheading: "generic.subheading",
|
||||
chroma.GenericTraceback: "generic.traceback",
|
||||
chroma.GenericUnderline: "generic.underline",
|
||||
chroma.Text: "text",
|
||||
chroma.TextWhitespace: "text.whitespace",
|
||||
chroma.TextSymbol: "text.symbol",
|
||||
chroma.TextPunctuation: "text.punctuation",
|
||||
}
|
||||
|
|
@ -8,8 +8,8 @@ import (
|
|||
"os/exec"
|
||||
"runtime"
|
||||
|
||||
md "github.com/github/gh-cli/markdown"
|
||||
"github.com/kballard/go-shellquote"
|
||||
md "github.com/vilmibm/go-termd"
|
||||
)
|
||||
|
||||
func OpenInBrowser(url string) error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue