mirror of
https://github.com/antonmedv/fx.git
synced 2024-08-17 14:10:46 +03:00
Add themes to js version
This commit is contained in:
parent
a7249fea5a
commit
289165d553
3
main.go
3
main.go
@ -57,6 +57,9 @@ func main() {
|
||||
case "--themes":
|
||||
themeTester()
|
||||
return
|
||||
case "--export-themes":
|
||||
exportThemes()
|
||||
return
|
||||
default:
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
71
npm/index.js
71
npm/index.js
@ -18,6 +18,7 @@ void async function main() {
|
||||
}
|
||||
if (flagHelp || (args.length === 0 && process.stdin.isTTY))
|
||||
return printUsage()
|
||||
const theme = themes(process.stdout.isTTY ? (process.env.FX_THEME || '1') : '0')
|
||||
await importFxrc(process.cwd())
|
||||
await importFxrc(os.homedir())
|
||||
let fd = 0 // stdin
|
||||
@ -35,17 +36,17 @@ void async function main() {
|
||||
for (const json of input) {
|
||||
array.push(json)
|
||||
}
|
||||
await runTransforms(array, args)
|
||||
await runTransforms(array, args, theme)
|
||||
} else {
|
||||
for (const json of input) {
|
||||
await runTransforms(json, args)
|
||||
await runTransforms(json, args, theme)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
const skip = Symbol('skip')
|
||||
|
||||
async function runTransforms(json, args) {
|
||||
async function runTransforms(json, args, theme) {
|
||||
const process = await import('node:process')
|
||||
let i, code, output = json
|
||||
for ([i, code] of args.entries()) try {
|
||||
@ -62,7 +63,7 @@ async function runTransforms(json, args) {
|
||||
else if (output === skip)
|
||||
return
|
||||
else
|
||||
console.log(stringify(output, process.stdout.isTTY))
|
||||
console.log(stringify(output, theme))
|
||||
|
||||
function printErr(err) {
|
||||
let pre = args.slice(0, i).join(' ')
|
||||
@ -520,14 +521,10 @@ function* parseJson(gen) {
|
||||
}
|
||||
}
|
||||
|
||||
function stringify(value, isPretty = false) {
|
||||
const colors = {
|
||||
key: isPretty ? '\x1b[1;34m' : '',
|
||||
string: isPretty ? '\x1b[32m' : '',
|
||||
number: isPretty ? '\x1b[36m' : '',
|
||||
boolean: isPretty ? '\x1b[35m' : '',
|
||||
null: isPretty ? '\x1b[38;5;243m' : '',
|
||||
reset: isPretty ? '\x1b[0m' : '',
|
||||
function stringify(value, theme) {
|
||||
function color(id, str) {
|
||||
if (theme[id] === '') return str
|
||||
return `\x1b[${theme[id]}m${str}\x1b[0m`
|
||||
}
|
||||
|
||||
function getIndent(level) {
|
||||
@ -536,38 +533,35 @@ function stringify(value, isPretty = false) {
|
||||
|
||||
function stringifyValue(value, level = 0) {
|
||||
if (typeof value === 'string') {
|
||||
return `${colors.string}${JSON.stringify(value)}${colors.reset}`
|
||||
return color(2, JSON.stringify(value))
|
||||
} else if (typeof value === 'number') {
|
||||
return `${colors.number}${value}${colors.reset}`
|
||||
return color(3, `${value}`)
|
||||
} else if (typeof value === 'bigint') {
|
||||
return `${colors.number}${value}${colors.reset}`
|
||||
return color(3, `${value}`)
|
||||
} else if (typeof value === 'boolean') {
|
||||
return `${colors.boolean}${value}${colors.reset}`
|
||||
return color(4, `${value}`)
|
||||
} else if (value === null || typeof value === 'undefined') {
|
||||
return `${colors.null}null${colors.reset}`
|
||||
return color(5, `null`)
|
||||
} else if (Array.isArray(value)) {
|
||||
if (value.length === 0) {
|
||||
return `[]`
|
||||
return color(0, `[]`)
|
||||
}
|
||||
const items = value
|
||||
.map((v) => `${getIndent(level + 1)}${stringifyValue(v, level + 1)}`)
|
||||
.join(',\n')
|
||||
return `[\n${items}\n${getIndent(level)}]`
|
||||
.map((v) => getIndent(level + 1) + stringifyValue(v, level + 1))
|
||||
.join(color(0, ',') + '\n')
|
||||
return color(0, '[') + '\n' + items + '\n' + getIndent(level) + color(0, ']')
|
||||
} else if (typeof value === 'object') {
|
||||
const keys = Object.keys(value)
|
||||
if (keys.length === 0) {
|
||||
return `{}`
|
||||
return color(0, '{}')
|
||||
}
|
||||
const entries = keys
|
||||
.map(
|
||||
(key) =>
|
||||
`${getIndent(level + 1)}${colors.key}"${key}"${colors.reset}: ${stringifyValue(
|
||||
value[key],
|
||||
level + 1,
|
||||
)}`,
|
||||
.map((key) =>
|
||||
getIndent(level + 1) + color(1, `"${key}"`) + color(0, ': ') +
|
||||
stringifyValue(value[key], level + 1),
|
||||
)
|
||||
.join(',\n')
|
||||
return `{\n${entries}\n${getIndent(level)}}`
|
||||
.join(color(0, ',') + '\n')
|
||||
return color(0, '{') + '\n' + entries + '\n' + getIndent(level) + color(0, '}')
|
||||
}
|
||||
throw new Error(`Unsupported value type: ${typeof value}`)
|
||||
}
|
||||
@ -575,6 +569,23 @@ function stringify(value, isPretty = false) {
|
||||
return stringifyValue(value)
|
||||
}
|
||||
|
||||
function themes(id) {
|
||||
const themes = {
|
||||
'0': ['', '', '', '', '', ''],
|
||||
'1': ['', '1;34', '32', '36', '35', '38;5;243'],
|
||||
'2': ['', '32', '34', '36', '35', '38;5;243'],
|
||||
'3': ['', '95', '93', '96', '31', '38;5;243'],
|
||||
'4': ['', '38;5;50', '38;5;39', '38;5;98', '38;5;205', '38;5;243'],
|
||||
'5': ['', '38;5;230', '38;5;221', '38;5;209', '38;5;209', '38;5;243'],
|
||||
'6': ['', '38;5;69', '38;5;78', '38;5;221', '38;5;203', '38;5;243'],
|
||||
'7': ['', '1;38;5;42', '1;38;5;213', '1;38;5;201', '1;38;5;201', '38;5;243'],
|
||||
'8': ['', '1;38;5;51', '38;5;195', '38;5;123', '38;5;50', '38;5;243'],
|
||||
'🔵': ['1;38;5;33', '38;5;33', '', '', '', ''],
|
||||
'🥝': ['38;5;179', '1;38;5;154', '38;5;82', '38;5;226', '38;5;226', '38;5;230'],
|
||||
}
|
||||
return themes[id] || themes['1']
|
||||
}
|
||||
|
||||
async function importFxrc(path) {
|
||||
const {join} = await import('node:path')
|
||||
const {pathToFileURL} = await import('node:url')
|
||||
|
98
theme.go
98
theme.go
@ -1,8 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
@ -24,6 +26,30 @@ type theme struct {
|
||||
|
||||
type color func(s []byte) []byte
|
||||
|
||||
func valueStyle(b []byte, selected, chunk bool) color {
|
||||
if selected {
|
||||
return currentTheme.Cursor
|
||||
} else if chunk {
|
||||
return currentTheme.String
|
||||
} else {
|
||||
switch b[0] {
|
||||
case '"':
|
||||
return currentTheme.String
|
||||
case 't', 'f':
|
||||
return currentTheme.Boolean
|
||||
case 'n':
|
||||
return currentTheme.Null
|
||||
case '{', '[', '}', ']':
|
||||
return currentTheme.Syntax
|
||||
default:
|
||||
if isDigit(b[0]) || b[0] == '-' {
|
||||
return currentTheme.Number
|
||||
}
|
||||
return noColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
themeNames = make([]string, 0, len(themes))
|
||||
for name := range themes {
|
||||
@ -234,60 +260,66 @@ func boldFg(color string) color {
|
||||
func themeTester() {
|
||||
title := lipgloss.NewStyle().Bold(true)
|
||||
for _, name := range themeNames {
|
||||
theme := themes[name]
|
||||
comma := string(theme.Syntax([]byte{','}))
|
||||
colon := string(theme.Syntax([]byte{':'}))
|
||||
t := themes[name]
|
||||
comma := string(t.Syntax([]byte{','}))
|
||||
colon := string(t.Syntax([]byte{':'}))
|
||||
|
||||
fmt.Println(title.Render(fmt.Sprintf("Theme %q", name)))
|
||||
fmt.Println(string(theme.Syntax([]byte("{"))))
|
||||
fmt.Println(string(t.Syntax([]byte("{"))))
|
||||
|
||||
fmt.Printf(" %v%v %v%v\n",
|
||||
string(theme.Key([]byte("\"string\""))),
|
||||
string(t.Key([]byte("\"string\""))),
|
||||
colon,
|
||||
string(theme.String([]byte("\"Fox jumps over the lazy dog\""))),
|
||||
string(t.String([]byte("\"Fox jumps over the lazy dog\""))),
|
||||
comma)
|
||||
|
||||
fmt.Printf(" %v%v %v%v\n",
|
||||
string(theme.Key([]byte("\"number\""))),
|
||||
string(t.Key([]byte("\"number\""))),
|
||||
colon,
|
||||
string(theme.Number([]byte("1234567890"))),
|
||||
string(t.Number([]byte("1234567890"))),
|
||||
comma)
|
||||
|
||||
fmt.Printf(" %v%v %v%v\n",
|
||||
string(theme.Key([]byte("\"boolean\""))),
|
||||
string(t.Key([]byte("\"boolean\""))),
|
||||
colon,
|
||||
string(theme.Boolean([]byte("true"))),
|
||||
string(t.Boolean([]byte("true"))),
|
||||
comma)
|
||||
fmt.Printf(" %v%v %v%v\n",
|
||||
string(theme.Key([]byte("\"null\""))),
|
||||
string(t.Key([]byte("\"null\""))),
|
||||
colon,
|
||||
string(theme.Null([]byte("null"))),
|
||||
string(t.Null([]byte("null"))),
|
||||
comma)
|
||||
fmt.Println(string(theme.Syntax([]byte("}"))))
|
||||
fmt.Println(string(t.Syntax([]byte("}"))))
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
func valueStyle(b []byte, selected, chunk bool) color {
|
||||
if selected {
|
||||
return currentTheme.Cursor
|
||||
} else if chunk {
|
||||
return currentTheme.String
|
||||
} else {
|
||||
switch b[0] {
|
||||
case '"':
|
||||
return currentTheme.String
|
||||
case 't', 'f':
|
||||
return currentTheme.Boolean
|
||||
case 'n':
|
||||
return currentTheme.Null
|
||||
case '{', '[', '}', ']':
|
||||
return currentTheme.Syntax
|
||||
default:
|
||||
if isDigit(b[0]) || b[0] == '-' {
|
||||
return currentTheme.Number
|
||||
}
|
||||
return noColor
|
||||
func exportThemes() {
|
||||
lipgloss.SetColorProfile(termenv.ANSI256) // Export in Terminal.app compatible colors
|
||||
placeholder := []byte{'_'}
|
||||
extract := func(b []byte) string {
|
||||
matches := regexp.
|
||||
MustCompile(`^\x1b\[(.+)m_`).
|
||||
FindStringSubmatch(string(b))
|
||||
if len(matches) == 0 {
|
||||
return ""
|
||||
} else {
|
||||
return matches[1]
|
||||
}
|
||||
}
|
||||
var export = map[string][]string{}
|
||||
for _, name := range themeNames {
|
||||
t := themes[name]
|
||||
export[name] = append(export[name], extract(t.Syntax(placeholder)))
|
||||
export[name] = append(export[name], extract(t.Key(placeholder)))
|
||||
export[name] = append(export[name], extract(t.String(placeholder)))
|
||||
export[name] = append(export[name], extract(t.Number(placeholder)))
|
||||
export[name] = append(export[name], extract(t.Boolean(placeholder)))
|
||||
export[name] = append(export[name], extract(t.Null(placeholder)))
|
||||
}
|
||||
data, err := json.Marshal(export)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(data))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user