Changed . token to _dot

This change allows the dotfiles to work with chezmoi (e.g: on windows)
and improves grepability with neovim/telescope
This commit is contained in:
2024-11-07 13:52:17 +00:00
parent 83b02bd753
commit 896af887ca
2351 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# Scripts and Source
This directory contains scripts and source files used to generate the `nu-themes` from their original sources.
## `make.nu`
Running `./make.nu` from inside the `src` directory will generate/update the main `nu-themes` directory.
Currently, two sources are used:
* The Lemnos Themes repository
* Custom Nushell themes located in the `custom-nu-themes` subdirectory
## Custom themes
Custom themes may be added to the `custom-nu-themes` directory. Follow the existing examples.
## Screenshot Preview Scripts
The `preview-*.nu` scripts are used to generate the screenshot examples. These currently require a Windows system. For instructions on usage, *"Use the Source, Luke"*. More documentation may be provided in a sequel.

View File

@@ -0,0 +1,115 @@
export def main [] {
const color_palette = {
rosewater: "#dc8a78"
flamingo: "#dd7878"
pink: "#ea76cb"
mauve: "#8839ef"
red: "#d20f39"
maroon: "#e64553"
peach: "#fe640b"
yellow: "#df8e1d"
green: "#40a02b"
teal: "#179299"
sky: "#04a5e5"
sapphire: "#209fb5"
blue: "#1e66f5"
lavender: "#7287fd"
text: "#4c4f69"
subtext1: "#5c5f77"
subtext0: "#6c6f85"
overlay2: "#7c7f93"
overlay1: "#8c8fa1"
overlay0: "#9ca0b0"
surface2: "#acb0be"
surface1: "#bcc0cc"
surface0: "#ccd0da"
crust: "#dce0e8"
mantle: "#e6e9ef"
base: "#eff1f5"
}
return {
separator: $color_palette.overlay0
leading_trailing_space_bg: { attr: "n" }
header: { fg: $color_palette.blue attr: "b" }
empty: $color_palette.lavender
bool: $color_palette.lavender
int: $color_palette.peach
duration: $color_palette.text
filesize: {|e|
if $e < 1mb {
$color_palette.green
} else if $e < 100mb {
$color_palette.yellow
} else if $e < 500mb {
$color_palette.peach
} else if $e < 800mb {
$color_palette.maroon
} else if $e > 800mb {
$color_palette.red
}
}
date: {|| (date now) - $in |
if $in < 1hr {
$color_palette.green
} else if $in < 1day {
$color_palette.yellow
} else if $in < 3day {
$color_palette.peach
} else if $in < 1wk {
$color_palette.maroon
} else if $in > 1wk {
$color_palette.red
}
}
range: $color_palette.text
float: $color_palette.text
string: $color_palette.text
nothing: $color_palette.text
binary: $color_palette.text
'cell-path': $color_palette.text
row_index: { fg: $color_palette.mauve attr: "b" }
record: $color_palette.text
list: $color_palette.text
block: $color_palette.text
hints: $color_palette.overlay1
search_result: { fg: $color_palette.red bg: $color_palette.text }
shape_and: { fg: $color_palette.pink attr: "b" }
shape_binary: { fg: $color_palette.pink attr: "b" }
shape_block: { fg: $color_palette.blue attr: "b" }
shape_bool: $color_palette.teal
shape_custom: $color_palette.green
shape_datetime: { fg: $color_palette.teal attr: "b" }
shape_directory: $color_palette.teal
shape_external: $color_palette.teal
shape_externalarg: { fg: $color_palette.green attr: "b" }
shape_filepath: $color_palette.teal
shape_flag: { fg: $color_palette.blue attr: "b" }
shape_float: { fg: $color_palette.pink attr: "b" }
shape_garbage: { fg: $color_palette.text bg: $color_palette.red attr: "b" }
shape_globpattern: { fg: $color_palette.teal attr: "b" }
shape_int: { fg: $color_palette.pink attr: "b" }
shape_internalcall: { fg: $color_palette.teal attr: "b" }
shape_list: { fg: $color_palette.teal attr: "b" }
shape_literal: $color_palette.blue
shape_match_pattern: $color_palette.green
shape_matching_brackets: { attr: "u" }
shape_nothing: $color_palette.teal
shape_operator: $color_palette.peach
shape_or: { fg: $color_palette.pink attr: "b" }
shape_pipe: { fg: $color_palette.pink attr: "b" }
shape_range: { fg: $color_palette.peach attr: "b" }
shape_record: { fg: $color_palette.teal attr: "b" }
shape_redirection: { fg: $color_palette.pink attr: "b" }
shape_signature: { fg: $color_palette.green attr: "b" }
shape_string: $color_palette.green
shape_string_interpolation: { fg: $color_palette.teal attr: "b" }
shape_table: { fg: $color_palette.blue attr: "b" }
shape_variable: $color_palette.pink
background: $color_palette.base
foreground: $color_palette.text
cursor: $color_palette.blue
}
}

View File

@@ -0,0 +1,115 @@
export def main [] {
const color_palette = {
rosewater: "#f5e0dc"
flamingo: "#f2cdcd"
pink: "#f5c2e7"
mauve: "#cba6f7"
red: "#f38ba8"
maroon: "#eba0ac"
peach: "#fab387"
yellow: "#f9e2af"
green: "#a6e3a1"
teal: "#94e2d5"
sky: "#89dceb"
sapphire: "#74c7ec"
blue: "#89b4fa"
lavender: "#b4befe"
text: "#cdd6f4"
subtext1: "#bac2de"
subtext0: "#a6adc8"
overlay2: "#9399b2"
overlay1: "#7f849c"
overlay0: "#6c7086"
surface2: "#585b70"
surface1: "#45475a"
surface0: "#313244"
base: "#1e1e2e"
mantle: "#181825"
crust: "#11111b"
}
return {
separator: $color_palette.overlay0
leading_trailing_space_bg: { attr: "n" }
header: { fg: $color_palette.blue attr: "b" }
empty: $color_palette.lavender
bool: $color_palette.lavender
int: $color_palette.peach
duration: $color_palette.text
filesize: {|e|
if $e < 1mb {
$color_palette.green
} else if $e < 100mb {
$color_palette.yellow
} else if $e < 500mb {
$color_palette.peach
} else if $e < 800mb {
$color_palette.maroon
} else if $e > 800mb {
$color_palette.red
}
}
date: {|| (date now) - $in |
if $in < 1hr {
$color_palette.green
} else if $in < 1day {
$color_palette.yellow
} else if $in < 3day {
$color_palette.peach
} else if $in < 1wk {
$color_palette.maroon
} else if $in > 1wk {
$color_palette.red
}
}
range: $color_palette.text
float: $color_palette.text
string: $color_palette.text
nothing: $color_palette.text
binary: $color_palette.text
'cell-path': $color_palette.text
row_index: { fg: $color_palette.mauve attr: "b" }
record: $color_palette.text
list: $color_palette.text
block: $color_palette.text
hints: $color_palette.overlay1
search_result: { fg: $color_palette.red bg: $color_palette.text }
shape_and: { fg: $color_palette.pink attr: "b" }
shape_binary: { fg: $color_palette.pink attr: "b" }
shape_block: { fg: $color_palette.blue attr: "b" }
shape_bool: $color_palette.teal
shape_custom: $color_palette.green
shape_datetime: { fg: $color_palette.teal attr: "b" }
shape_directory: $color_palette.teal
shape_external: $color_palette.teal
shape_externalarg: { fg: $color_palette.green attr: "b" }
shape_filepath: $color_palette.teal
shape_flag: { fg: $color_palette.blue attr: "b" }
shape_float: { fg: $color_palette.pink attr: "b" }
shape_garbage: { fg: $color_palette.text bg: $color_palette.red attr: "b" }
shape_globpattern: { fg: $color_palette.teal attr: "b" }
shape_int: { fg: $color_palette.pink attr: "b" }
shape_internalcall: { fg: $color_palette.teal attr: "b" }
shape_list: { fg: $color_palette.teal attr: "b" }
shape_literal: $color_palette.blue
shape_match_pattern: $color_palette.green
shape_matching_brackets: { attr: "u" }
shape_nothing: $color_palette.teal
shape_operator: $color_palette.peach
shape_or: { fg: $color_palette.pink attr: "b" }
shape_pipe: { fg: $color_palette.pink attr: "b" }
shape_range: { fg: $color_palette.peach attr: "b" }
shape_record: { fg: $color_palette.teal attr: "b" }
shape_redirection: { fg: $color_palette.pink attr: "b" }
shape_signature: { fg: $color_palette.green attr: "b" }
shape_string: $color_palette.green
shape_string_interpolation: { fg: $color_palette.teal attr: "b" }
shape_table: { fg: $color_palette.blue attr: "b" }
shape_variable: $color_palette.pink
background: $color_palette.base
foreground: $color_palette.text
cursor: $color_palette.blue
}
}

View File

@@ -0,0 +1,90 @@
export def main [] {
return {
# color for nushell primitives
separator: white
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
header: green_bold
empty: blue
# Closures can be used to choose colors for specific values.
# The value (in this case, a bool) is piped into the closure.
bool: {|| if $in { 'light_cyan' } else { 'light_gray' } }
int: white
filesize: {|e|
if $e == 0b {
'white'
} else if $e < 1mb {
'cyan'
} else { 'blue' }
}
duration: white
date: {|| (date now) - $in |
if $in < 1hr {
'purple'
} else if $in < 6hr {
'red'
} else if $in < 1day {
'yellow'
} else if $in < 3day {
'green'
} else if $in < 1wk {
'light_green'
} else if $in < 6wk {
'cyan'
} else if $in < 52wk {
'blue'
} else { 'dark_gray' }
}
range: white
float: white
string: white
nothing: white
binary: white
'cell-path': white
row_index: green_bold
record: white
list: white
block: white
hints: dark_gray
search_result: {bg: red fg: white}
shape_and: purple_bold
shape_binary: purple_bold
shape_block: blue_bold
shape_bool: light_cyan
shape_closure: green_bold
shape_custom: green
shape_datetime: cyan_bold
shape_directory: cyan
shape_external: cyan
shape_externalarg: green_bold
shape_filepath: cyan
shape_flag: blue_bold
shape_float: purple_bold
# shapes are used to change the cli syntax highlighting
shape_garbage: { fg: white bg: red attr: b}
shape_globpattern: cyan_bold
shape_int: purple_bold
shape_internalcall: cyan_bold
shape_list: cyan_bold
shape_literal: blue
shape_match_pattern: green
shape_matching_brackets: { attr: u }
shape_nothing: light_cyan
shape_operator: yellow
shape_or: purple_bold
shape_pipe: purple_bold
shape_range: yellow_bold
shape_record: cyan_bold
shape_redirection: purple_bold
shape_signature: green_bold
shape_string: green
shape_string_interpolation: cyan_bold
shape_table: blue_bold
shape_variable: purple
shape_vardecl: purple
background: "#767676"
foreground: "#f2f2f2"
cursor: "#c50f1f"
}
}

View File

@@ -0,0 +1,90 @@
export def main [] {
return {
# color for nushell primitives
separator: dark_gray
leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off
header: green_bold
empty: blue
# Closures can be used to choose colors for specific values.
# The value (in this case, a bool) is piped into the closure.
bool: {|| if $in { 'dark_cyan' } else { 'dark_gray' } }
int: dark_gray
filesize: {|e|
if $e == 0b {
'dark_gray'
} else if $e < 1mb {
'cyan_bold'
} else { 'blue_bold' }
}
duration: dark_gray
date: {|| (date now) - $in |
if $in < 1hr {
'purple'
} else if $in < 6hr {
'red'
} else if $in < 1day {
'yellow'
} else if $in < 3day {
'green'
} else if $in < 1wk {
'light_green'
} else if $in < 6wk {
'cyan'
} else if $in < 52wk {
'blue'
} else { 'dark_gray' }
}
range: dark_gray
float: dark_gray
string: dark_gray
nothing: dark_gray
binary: dark_gray
'cell-path': dark_gray
row_index: green_bold
record: white
list: white
block: white
hints: dark_gray
search_result: {fg: white bg: red}
shape_and: purple_bold
shape_binary: purple_bold
shape_block: blue_bold
shape_bool: light_cyan
shape_closure: green_bold
shape_custom: green
shape_datetime: cyan_bold
shape_directory: cyan
shape_external: cyan
shape_externalarg: green_bold
shape_filepath: cyan
shape_flag: blue_bold
shape_float: purple_bold
# shapes are used to change the cli syntax highlighting
shape_garbage: { fg: white bg: red attr: b}
shape_globpattern: cyan_bold
shape_int: purple_bold
shape_internalcall: cyan_bold
shape_list: cyan_bold
shape_literal: blue
shape_match_pattern: green
shape_matching_brackets: { attr: u }
shape_nothing: light_cyan
shape_operator: yellow
shape_or: purple_bold
shape_pipe: purple_bold
shape_range: yellow_bold
shape_record: cyan_bold
shape_redirection: purple_bold
shape_signature: green_bold
shape_string: green
shape_string_interpolation: cyan_bold
shape_table: blue_bold
shape_variable: purple
shape_vardecl: purple
background: "#f2f2f2"
foreground: "#767676"
cursor: "#c50f1f"
}
}

View File

@@ -0,0 +1,84 @@
export def main [] {
return {
separator: "#a9b1d6"
leading_trailing_space_bg: { attr: "n" }
header: { fg: "#9ece6a" attr: "b" }
empty: "#7aa2f7"
bool: {|| if $in { "#7dcfff" } else { "light_gray" } }
int: "#a9b1d6"
filesize: {|e|
if $e == 0b {
"#a9b1d6"
} else if $e < 1mb {
"#7dcfff"
} else {{ fg: "#7aa2f7" }}
}
duration: "#a9b1d6"
date: {|| (date now) - $in |
if $in < 1hr {
{ fg: "#f7768e" attr: "b" }
} else if $in < 6hr {
"#f7768e"
} else if $in < 1day {
"#e0af68"
} else if $in < 3day {
"#9ece6a"
} else if $in < 1wk {
{ fg: "#9ece6a" attr: "b" }
} else if $in < 6wk {
"#7dcfff"
} else if $in < 52wk {
"#7aa2f7"
} else { "dark_gray" }
}
range: "#a9b1d6"
float: "#a9b1d6"
string: "#a9b1d6"
nothing: "#a9b1d6"
binary: "#a9b1d6"
cell-path: "#a9b1d6"
row_index: { fg: "#9ece6a" attr: "b" }
record: "#a9b1d6"
list: "#a9b1d6"
block: "#a9b1d6"
hints: "dark_gray"
search_result: { fg: "#f7768e" bg: "#a9b1d6" }
shape_and: { fg: "#bb9af7" attr: "b" }
shape_binary: { fg: "#bb9af7" attr: "b" }
shape_block: { fg: "#7aa2f7" attr: "b" }
shape_bool: "#7dcfff"
shape_custom: "#9ece6a"
shape_datetime: { fg: "#7dcfff" attr: "b" }
shape_directory: "#7dcfff"
shape_external: "#7dcfff"
shape_externalarg: { fg: "#9ece6a" attr: "b" }
shape_filepath: "#7dcfff"
shape_flag: { fg: "#7aa2f7" attr: "b" }
shape_float: { fg: "#bb9af7" attr: "b" }
shape_garbage: { fg: "#FFFFFF" bg: "#FF0000" attr: "b" }
shape_globpattern: { fg: "#7dcfff" attr: "b" }
shape_int: { fg: "#bb9af7" attr: "b" }
shape_internalcall: { fg: "#7dcfff" attr: "b" }
shape_list: { fg: "#7dcfff" attr: "b" }
shape_literal: "#7aa2f7"
shape_match_pattern: "#9ece6a"
shape_matching_brackets: { attr: "u" }
shape_nothing: "#7dcfff"
shape_operator: "#e0af68"
shape_or: { fg: "#bb9af7" attr: "b" }
shape_pipe: { fg: "#bb9af7" attr: "b" }
shape_range: { fg: "#e0af68" attr: "b" }
shape_record: { fg: "#7dcfff" attr: "b" }
shape_redirection: { fg: "#bb9af7" attr: "b" }
shape_signature: { fg: "#9ece6a" attr: "b" }
shape_string: "#9ece6a"
shape_string_interpolation: { fg: "#7dcfff" attr: "b" }
shape_table: { fg: "#7aa2f7" attr: "b" }
shape_variable: "#bb9af7"
background: "#1a1b26"
foreground: "#c0caf5"
cursor: "#c0caf5"
}
}

View File

@@ -0,0 +1,280 @@
#!/usr/bin/env nu
use .../stdlib-candidate/std-rfc str
let current_dir = ($env.CURRENT_FILE | path dirname)
let LEMNOS_SOURCE = {
dir: ($current_dir | path join "lemnos" "themes")
local_repo: ($current_dir | path join "lemnos")
remote_repo: "https://github.com/lemnos/theme.sh"
}
let CUSTOM_SOURCE = {
dir: ($current_dir | path join "custom-nu-themes")
}
let themes_dir = ($current_dir | path join "../nu-themes")
def info [msg: string, --no-newline (-n)] {
print --no-newline=$no_newline $"(ansi green)[INFO](ansi reset) ($msg)"
}
def err [msg: string, --no-newline (-n)] {
print --no-newline=$no_newline $"(ansi red_bold)[ERR](ansi reset) ($msg)"
}
def warn [msg: string, --no-newline (-n)] {
print --no-newline=$no_newline $"(ansi yellow)[WARNING](ansi reset) ($msg)"
}
# For lemnos themes, create the color_config from the lemnos theme
# definition.
# Custom Nushell themes should be defined in themes/src/custom-nu-themes
# and should return a color_config record in the main function.
def make_color_config [ name: string, source: string = "lemnos" ] {
match $source {
"lemnos" => {
let colors = (
open ($LEMNOS_SOURCE.dir | path join $name)
| lines --skip-empty
| find --invert --regex '^#'
| split column " "
| rename name rgb
| transpose -r
| into record
)
return $"
# Retrieve the theme settings
export def main [] {
return {
binary: '($colors.color5)'
block: '($colors.color4)'
cell-path: '($colors.color7)'
closure: '($colors.color6)'
custom: '($colors.color15)'
duration: '($colors.color3)'
float: '($colors.color9)'
glob: '($colors.color15)'
int: '($colors.color5)'
list: '($colors.color6)'
nothing: '($colors.color1)'
range: '($colors.color3)'
record: '($colors.color6)'
string: '($colors.color2)'
bool: {|| if $in { '($colors.color14)' } else { '($colors.color3)' } }
date: {|| (char lparen)date now(char rparen) - $in |
if $in < 1hr {
{ fg: '($colors.color1)' attr: 'b' }
} else if $in < 6hr {
'($colors.color1)'
} else if $in < 1day {
'($colors.color3)'
} else if $in < 3day {
'($colors.color2)'
} else if $in < 1wk {
{ fg: '($colors.color2)' attr: 'b' }
} else if $in < 6wk {
'($colors.color6)'
} else if $in < 52wk {
'($colors.color4)'
} else { 'dark_gray' }
}
filesize: {|e|
if $e == 0b {
'($colors.color7)'
} else if $e < 1mb {
'($colors.color6)'
} else {{ fg: '($colors.color4)' }}
}
shape_and: { fg: '($colors.color5)' attr: 'b' }
shape_binary: { fg: '($colors.color5)' attr: 'b' }
shape_block: { fg: '($colors.color4)' attr: 'b' }
shape_bool: '($colors.color14)'
shape_closure: { fg: '($colors.color6)' attr: 'b' }
shape_custom: '($colors.color2)'
shape_datetime: { fg: '($colors.color6)' attr: 'b' }
shape_directory: '($colors.color6)'
shape_external: '($colors.color6)'
shape_external_resolved: '($colors.color14)'
shape_externalarg: { fg: '($colors.color2)' attr: 'b' }
shape_filepath: '($colors.color6)'
shape_flag: { fg: '($colors.color4)' attr: 'b' }
shape_float: { fg: '($colors.color9)' attr: 'b' }
shape_garbage: { fg: '#FFFFFF' bg: '#FF0000' attr: 'b' }
shape_glob_interpolation: { fg: '($colors.color6)' attr: 'b' }
shape_globpattern: { fg: '($colors.color6)' attr: 'b' }
shape_int: { fg: '($colors.color5)' attr: 'b' }
shape_internalcall: { fg: '($colors.color6)' attr: 'b' }
shape_keyword: { fg: '($colors.color5)' attr: 'b' }
shape_list: { fg: '($colors.color6)' attr: 'b' }
shape_literal: '($colors.color4)'
shape_match_pattern: '($colors.color2)'
shape_matching_brackets: { attr: 'u' }
shape_nothing: '($colors.color1)'
shape_operator: '($colors.color3)'
shape_or: { fg: '($colors.color5)' attr: 'b' }
shape_pipe: { fg: '($colors.color5)' attr: 'b' }
shape_range: { fg: '($colors.color3)' attr: 'b' }
shape_raw_string: { fg: '($colors.color15)' attr: 'b' }
shape_record: { fg: '($colors.color6)' attr: 'b' }
shape_redirection: { fg: '($colors.color5)' attr: 'b' }
shape_signature: { fg: '($colors.color2)' attr: 'b' }
shape_string: '($colors.color2)'
shape_string_interpolation: { fg: '($colors.color6)' attr: 'b' }
shape_table: { fg: '($colors.color4)' attr: 'b' }
shape_vardecl: { fg: '($colors.color4)' attr: 'u' }
shape_variable: '($colors.color5)'
foreground: '($colors.foreground)'
background: '($colors.background)'
cursor: '($colors.cursor)'
empty: '($colors.color4)'
header: { fg: '($colors.color2)' attr: 'b' }
hints: '($colors.color8)'
leading_trailing_space_bg: { attr: 'n' }
row_index: { fg: '($colors.color2)' attr: 'b' }
search_result: { fg: '($colors.color1)' bg: '($colors.color7)' }
separator: '($colors.color7)'
}
}
"
}
"custom" => {
let original_file = (
{
parent: $CUSTOM_SOURCE.dir
stem: $name
extension: 'nu'
}
| path join
)
# Add starting and ending linebreaks for str-dedent
return $"\n# Retrieve the theme settings\n(open $original_file)\n"
}
}
}
def make_theme [ name: string, origin: string = "lemnos" ] {
# Generate the theme depending on what type/origin it is
let main_command = ((make_color_config $name $origin) | str dedent)
let update_terminal_command = $"
# Update terminal colors
export def \"update terminal\" [] {
let theme = \(main)
# Set terminal colors
let osc_screen_foreground_color = '10;'
let osc_screen_background_color = '11;'
let osc_cursor_color = '12;'
$\"
\(ansi -o $osc_screen_foreground_color)\($theme.foreground)\(char bel)
\(ansi -o $osc_screen_background_color)\($theme.background)\(char bel)
\(ansi -o $osc_cursor_color)\($theme.cursor)\(char bel)
\"
# Line breaks above are just for source readability
# but create extra whitespace when activating. Collapse
# to one line and print with no-newline
| str replace --all \"\\n\" ''
| print -n $\"\($in)\\r\"
}
"
| str dedent
let set_color_config_command = $"
# Update the Nushell configuration
export def --env \"set color_config\" [] {
$env.config.color_config = \(main)
}
"
| str dedent
let activate_command = $"
export module activate {
export-env {
set color_config
update terminal
}
}
# Activate the theme when sourced
use activate
"
| str dedent
# Combine into the final theme file
[
$main_command
$set_color_config_command
$update_terminal_command
$activate_command
]
| str join "\n\n"
#| str dedent
| save --force ({
parent: $themes_dir
stem: $"($name)"
extension: "nu"
} | path join)
}
def main [] {
mkdir $themes_dir
if ($LEMNOS_SOURCE.local_repo | path exists) {
warn "local copy of Lemnos' themes already exists"
info "updating local copy"
try {
git -C $LEMNOS_SOURCE.local_repo pull origin master
} catch {
err "failed updating local copy"
}
} else {
info "cloning Lemnos' themes"
try {
git clone $LEMNOS_SOURCE.remote_repo $LEMNOS_SOURCE.local_repo
# Rename 3024, since modules can't be ints
git -C $LEMNOS_SOURCE.local_repo mv "themes/3024" "themes/3024r"
} catch {
error make --unspanned { msg: "failed cloning local copy" }
}
}
let themes: table<name: string, source: string> = (
ls $LEMNOS_SOURCE.dir
| insert source "lemnos"
| append (ls $CUSTOM_SOURCE.dir | insert source "custom")
| update name { path parse | get stem }
| select name source
)
let failed = $themes | each { |t|
info -n $"Converting ($t.name) \r"
try {
make_theme $t.name $t.source
} catch { |e|
err $"Converting ($t.name) failed: ($e.msg)"
$t
}
}
info -n $"Completed converting (($themes | length) - ($failed | length)) themes \r"
print ''
if not ($failed | is-empty) {
warn $"The following ($failed | length) themes have failed:"
print $failed
} else {
print "all done"
}
}

View File

@@ -0,0 +1,224 @@
# This script is meant to be run from the nu_scripts/themes/src
# folder inside this repository.
#
# Recommended:
# * Close any other Terminal tabs
# * Set your tab title to something like "Theme Preview"
# * Size your terminal so that theme previews just fit without
# too great a border
# * Place your terminal window against a separate solid
# background to reduce artifacts
def save_screenshot [ method, theme_name ] {
use .../stdlib-candidate/std-rfc/str
match $method {
# This method for generating terminal screenshots uses
# a pure-PowerShell script. The caveat is that Windows
# Security may interpret this as a threat and refuse to
# execute. In that case, temporarily turn off Real-Time
# Protection, run the script, and then immediately
# re-enable protection.
# This method should work from either WSL or Nushell
# for Windows
"powershell" => {
let ps_script = $"
use .. *
source ($name)
clear
sleep 100ms
print `Theme name: '($theme_name)'`
print -n \(preview theme small | table -e)
sleep 250ms
$Host.UI.RawUI.WindowTitle = 'Theme Preview'
Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.Sendkeys]::SendWait\('%{Prtsc}')
[Windows.Forms.Sendkeys]::SendWait\('%{Prtsc}')
[Windows.Forms.Sendkeys]::SendWait\('%{Prtsc}')
sleep 1
[Windows.Forms.Clipboard]::GetImage\().Save\('($theme_name).png', [System.Drawing.Imaging.ImageFormat]::Png)
"
| str dedent
$"powershell.exe -c \"
($ps_script)
\""
}
# Requires MiniCap, a utility for capturing screenshots on Windows
"minicap" => {
$'
use .. *
source ($name)
clear
sleep 100ms
print `Theme name: '($theme_name)'`
print -n \(preview theme small | table -e)
sleep 250ms
c:\\apps\\MiniCap\\MiniCap.exe -captureactivewin -bordershadow -save ($theme_name).png -closeapp -exit
'
}
# Requires asciinema (Linux/Mac only), agg (asciinema to gif), and ffmpeg
# Currently uses Caskaydia Cover Nerd Font installed in user's local fonts
"asciinema" => {
print $theme_name
$"
let asciinema_nu_script = $\"
use .. *
sleep 200ms
source ../nu-themes/($theme_name).nu
clear
print 'Theme: ($theme_name)'
print -n \\\(preview theme small)
sleep 200ms
print ""
\"
mkdir conversions
asciinema rec -c $'nu -c "\($asciinema_nu_script)\"' ./conversions/($theme_name).cast
# Define terminal colors for asciinema-to-gif converter
let sgr_colors = {
black: r#'000000'#
red: r#'800000'#
green: r#'808000'#
yellow: r#'008000'#
blue: r#'000080'#
magenta: r#'800080'#
cyan: r#'008080'#
white: r#'c0c0c0'#
gray: r#'808080'#
bright_red: r#'ff0000'#
bright_green: r#'00ff00'#
bright_yellow: r#'ffff00'#
bright_blue: r#'0000ff'#
bright_magenta: r#'ff00ff'#
bright_cyan: r#'00ffff'#
bright_white: r#'ffffff'#
}
use ../nu-themes/($theme_name).nu
let theme_fg_bg = {
background: \(\(($theme_name)).background | str replace '#' '')
foreground: \(\(($theme_name)).foreground | str replace '#' '')
}
# Combine the theme foreground/background with the SGR colors for an agg theme
let agg_theme = {
...$theme_fg_bg
...$sgr_colors
}
| transpose key value
| get value
| str join ","
# Convert asciinema recording to gif
# Line-height of 1.2 to keep table drawing characters together
agg -v --font-size=24 --renderer=resvg --line-height 1.2 --font-dir ~/.nix-profile/share/fonts/truetype/NerdFonts --font-family \"CaskaydiaCove NFM\" --theme $agg_theme ./conversions/($theme_name).cast ./conversions/($theme_name).gif
rm ./conversions/($theme_name).cast
ffmpeg -i ./conversions/($theme_name).gif -vf 'select=eq\\\(n\\,1)' -fps_mode vfr -q:v 2 -frames:v 1 -update 1 ../screenshots/($theme_name).png
rm ./conversions/($theme_name).gif
"
}
}
}
def "preview generate screenshots" [screenshot_method, theme_count = 10_000] {
use .../stdlib-candidate/std-rfc str
let themes = (
"../nu-themes/"
| path expand
| path join "*.nu"
| into glob
| ls $in
)
for theme in $themes {
let name = $theme.name
let basename = ($theme.name | path parse | get stem)
let filename = (
"../screenshots"
| path join $'($name | path parse | get stem).png'
)
let script = $"
#use .. *
#source ($name)
#clear
#sleep 100ms
#print `Theme name: '($basename)'`
#print -n \(preview theme small | table -e)
#sleep 250ms
(save_screenshot $screenshot_method $basename)
"
# Run with default config
# nu -n -c $script
nu -n -c $"(save_screenshot $screenshot_method $basename)"
}
}
def "preview generate readme" [] {
use .../stdlib-candidate/std-rfc str
# README Title
"# Screenshots of Theme Previews\n\n"
| save -f "../screenshots/README.md"
# Screenshot for each Theme
"../screenshots/*.png"
| into glob
| ls $in
| get name
| sort
| each {|screenshot|
let theme_name = (
$screenshot
| path parse
| get stem
)
let screenshot_file = (
$screenshot
| path parse
| $"($in.stem).($in.extension)"
)
$"
### Theme name: '($theme_name)'
![($theme_name)]\(($screenshot_file))
"
| str dedent
| save -a "../screenshots/README.md"
}
| ignore
}
def main [screenshot_method] {
use .../stdlib-candidate/std-rfc/str
if $env.PWD != $env.FILE_PWD {
"
Please run this script from the directory where it resides using:
nu preview-screenshot-script.nu
"
| str dedent
| print -e $in
return
} else {
mkdir ../screenshots
preview generate screenshots $screenshot_method
preview generate readme
}
}