[colorschemes] rewrite the generator from scratch

This commit is contained in:
Dmytro Meleshko 2021-05-30 17:53:53 +03:00
parent 74a20d6db2
commit 2be34dfad7
17 changed files with 437 additions and 303 deletions

View file

@ -1,25 +0,0 @@
# https://tech.davis-hansson.com/p/make/
SHELL := bash
.ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
.PHONY: all clean
OUT_DIR := out
OUT_FILES := iterm.itermcolors kitty.conf vim.vim setvtrgb.txt zsh.zsh termux.properties variables.css colorscheme.scss prismjs-theme.css vscode-colorCustomizations.json xfce4-terminal.theme
all: $(OUT_DIR) $(addprefix $(OUT_DIR)/,$(OUT_FILES))
clean:
rm -rv $(OUT_DIR)
$(OUT_DIR):
mkdir -p $@
$(OUT_DIR)/%: %.py _theme.py $(OUT_DIR)
python3 ./$< > $@
$(OUT_DIR)/prismjs-theme.css: prismjs-theme-src.css

View file

@ -1,50 +0,0 @@
#!/usr/bin/env python3
# base16-eighties by Chris Kempson (http://chriskempson.com)
base16_name = "eighties"
name = "base16-" + base16_name
is_dark = True
base16_colors = [
"#2d2d2d", # 0
"#393939", # 1
"#515151", # 2
"#747369", # 3
"#a09f93", # 4
"#d3d0c8", # 5
"#e8e6df", # 6
"#f2f0ec", # 7
"#f2777a", # 8
"#f99157", # 9
"#ffcc66", # a
"#99cc99", # b
"#66cccc", # c
"#6699cc", # d
"#cc99cc", # e
"#d27b53", # f
]
bg = base16_colors[0x0]
fg = base16_colors[0x5]
cursor_bg = fg
cursor_fg = bg
selection_bg = base16_colors[0x2]
selection_fg = fg
ansi_colors = [
base16_colors[int(i, 16)] for i in "0 8 B A D E C 5 3 8 B A D E C 7 9 F 1 2 4 6".split()
]
link_color = ansi_colors[0xC]
css_variables_prefix = "dotfiles-colorscheme-"
css_variables = {
"bg": bg,
"fg": fg,
"selection-bg": selection_bg,
"selection-fg": selection_fg,
"cursor-bg": cursor_bg,
"cursor-fg": cursor_fg,
**{"base-{:02X}".format(index): color for index, color in enumerate(base16_colors)},
}

View file

@ -1,13 +0,0 @@
#!/usr/bin/env python3
# TODO: Prefix the name with an underscore when I rewrite the theme generator,
# see <https://sass-lang.com/documentation/at-rules/use#partials>.
import _theme as theme
print('$is-dark: {};'.format("true" if theme.is_dark else "false"))
for var_name, color in theme.css_variables.items():
print("${}: {};".format(var_name, color))
print("$base: ({});".format(', '.join(theme.base16_colors)))
print("$ansi: ({});".format(', '.join(theme.ansi_colors)))

View file

@ -1,49 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
print(
"""\
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>\
"""
)
def print_color(key_name, color):
r, g, b = [float(int(color[2 * i + 1:2 * i + 3], 16)) / 255 for i in range(3)]
print(
"""\
<key>{} Color</key>
<dict>
<key>Color Space</key>
<string>sRGB</string>
<key>Red Component</key>
<real>{}</real>
<key>Green Component</key>
<real>{}</real>
<key>Blue Component</key>
<real>{}</real>
</dict>\
""".format(key_name, r, g, b)
)
print_color("Background", theme.bg)
print_color("Foreground", theme.fg)
print_color("Bold", theme.fg)
print_color("Cursor", theme.cursor_bg)
print_color("Cursor Text", theme.cursor_fg)
print_color("Selection Color", theme.selection_bg)
print_color("Selected Text Color", theme.selection_fg)
for index, color in enumerate(theme.ansi_colors[:16]):
print_color("Ansi " + str(index), color)
print_color("Link", theme.link_color)
print("""\
</dict>
</plist>\
""")

View file

@ -1,28 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
def print_color(key_name, color):
print("{} {}".format(key_name, color))
print_color("background", theme.bg)
print_color("foreground", theme.fg)
print_color("cursor", theme.cursor_bg)
print_color("cursor_text_color", theme.cursor_fg)
print_color("selection_background", theme.selection_bg)
print_color("selection_foreground", theme.selection_fg)
for index, color in enumerate(theme.ansi_colors[:16]):
print_color("color" + str(index), color)
print_color("url_color", theme.link_color)
print_color("active_border_color", theme.ansi_colors[2])
print_color("inactive_border_color", theme.ansi_colors[8])
print_color("bell_border_color", theme.ansi_colors[1])
print_color("active_tab_foreground", theme.base16_colors[0x1])
print_color("active_tab_background", theme.base16_colors[0xB])
print_color("inactive_tab_foreground", theme.base16_colors[0x4])
print_color("inactive_tab_background", theme.base16_colors[0x1])
print_color("tab_bar_background", theme.base16_colors[0x1])

436
colorschemes/main.py Executable file
View file

@ -0,0 +1,436 @@
#!/usr/bin/env python3
import json
import os
from abc import abstractmethod
from typing import Dict, Iterable, List, Protocol, TextIO, runtime_checkable
__dir__ = os.path.dirname(__file__)
class Color:
def __init__(self, r: int, g: int, b: int) -> None:
assert 0 <= r <= 0xff
assert 0 <= g <= 0xff
assert 0 <= b <= 0xff
self.r = r
self.g = g
self.b = b
@classmethod
def from_hex(cls, s: str) -> "Color":
assert len(s) == 6
return Color(int(s[0:2], 16), int(s[2:4], 16), int(s[4:6], 16))
@property
def css_hex(self) -> str:
return "#{:02x}{:02x}{:02x}".format(self.r, self.g, self.b)
@property
def hex(self) -> str:
return "{:02x}{:02x}{:02x}".format(self.r, self.g, self.b)
def __getitem__(self, index: int) -> int:
if index == 0:
return self.r
elif index == 1:
return self.g
elif index == 2:
return self.b
else:
raise IndexError("color component index out of range")
def __iter__(self) -> Iterable[int]:
yield self.r
yield self.g
yield self.b
BASE16_TO_ANSI_MAPPING: List[int] = [
0x0, 0x8, 0xB, 0xA, 0xD, 0xE, 0xC, 0x5, # 0x0
0x3, 0x8, 0xB, 0xA, 0xD, 0xE, 0xC, 0x7, # 0x8
0x9, 0xF, 0x1, 0x2, 0x4, 0x6, # 0x10
] # yapf: disable
ANSI_TO_BASE16_MAPPING: List[int] = [BASE16_TO_ANSI_MAPPING.index(i) for i in range(16)]
@runtime_checkable
class Theme(Protocol):
@property
@abstractmethod
def base16_name(self) -> str:
raise NotImplementedError()
@property
@abstractmethod
def is_dark(self) -> bool:
raise NotImplementedError()
@property
@abstractmethod
def base16_colors(self) -> List[Color]:
raise NotImplementedError()
@property
def name(self) -> str:
return "base16-{}".format(self.base16_name)
@property
def bg(self) -> Color:
return self.base16_colors[0x0]
@property
def fg(self) -> Color:
return self.base16_colors[0x5]
@property
def cursor_bg(self) -> Color:
return self.fg
@property
def cursor_fg(self) -> Color:
return self.bg
@property
def selection_bg(self) -> Color:
return self.base16_colors[0x2]
@property
def selection_fg(self) -> Color:
return self.fg
@property
def ansi_colors(self) -> List[Color]:
return [self.base16_colors[i] for i in BASE16_TO_ANSI_MAPPING]
@property
def link_color(self) -> Color:
return self.ansi_colors[0xC]
@property
def css_variables(self) -> Dict[str, Color]:
d = {
"bg": self.bg,
"fg": self.fg,
"selection-bg": self.selection_bg,
"selection-fg": self.selection_fg,
"cursor-bg": self.cursor_bg,
"cursor-fg": self.cursor_fg,
}
for index, color in enumerate(self.base16_colors):
d["base-{:02X}".format(index)] = color
return d
class MyTheme(Theme):
base16_name = "eighties"
is_dark = True
base16_colors = [
Color.from_hex("2d2d2d"), # 0
Color.from_hex("393939"), # 1
Color.from_hex("515151"), # 2
Color.from_hex("747369"), # 3
Color.from_hex("a09f93"), # 4
Color.from_hex("d3d0c8"), # 5
Color.from_hex("e8e6df"), # 6
Color.from_hex("f2f0ec"), # 7
Color.from_hex("f2777a"), # 8
Color.from_hex("f99157"), # 9
Color.from_hex("ffcc66"), # a
Color.from_hex("99cc99"), # b
Color.from_hex("66cccc"), # c
Color.from_hex("6699cc"), # d
Color.from_hex("cc99cc"), # e
Color.from_hex("d27b53"), # f
]
@runtime_checkable
class ThemeGenerator(Protocol):
@abstractmethod
def file_name(self) -> str:
raise NotImplementedError()
@abstractmethod
def generate(self, theme: Theme, output: TextIO) -> None:
raise NotImplementedError()
class ThemeGeneratorKitty(ThemeGenerator):
def file_name(self) -> str:
return "kitty.conf"
def generate(self, theme: Theme, output: TextIO) -> None:
def write_color(key_name: str, color: Color) -> None:
output.write("{} {}\n".format(key_name, color.css_hex))
write_color("background", theme.bg)
write_color("foreground", theme.fg)
write_color("cursor", theme.cursor_bg)
write_color("cursor_text_color", theme.cursor_fg)
write_color("selection_background", theme.selection_bg)
write_color("selection_foreground", theme.selection_fg)
for index, color in enumerate(theme.ansi_colors[:16]):
write_color("color{}".format(index), color)
write_color("url_color", theme.link_color)
write_color("active_border_color", theme.ansi_colors[2])
write_color("inactive_border_color", theme.ansi_colors[8])
write_color("bell_border_color", theme.ansi_colors[1])
write_color("active_tab_foreground", theme.base16_colors[0x1])
write_color("active_tab_background", theme.base16_colors[0xB])
write_color("inactive_tab_foreground", theme.base16_colors[0x4])
write_color("inactive_tab_background", theme.base16_colors[0x1])
write_color("tab_bar_background", theme.base16_colors[0x1])
class ThemeGeneratorTermux(ThemeGenerator):
def file_name(self) -> str:
return "termux.properties"
def generate(self, theme: Theme, output: TextIO) -> None:
def write_color(key_name: str, color: Color) -> None:
output.write("{}={}\n".format(key_name, color.css_hex))
write_color("background", theme.bg)
write_color("foreground", theme.fg)
write_color("cursor", theme.cursor_bg)
for index, color in enumerate(theme.ansi_colors[:16]):
write_color("color{}".format(index), color)
class ThemeGeneratorZsh(ThemeGenerator):
def file_name(self) -> str:
return "zsh.zsh"
def generate(self, theme: Theme, output: TextIO) -> None:
def write_color(key_name: str, color: Color) -> None:
output.write("colorscheme_{}={}\n".format(key_name, color.hex))
write_color("bg", theme.bg)
write_color("fg", theme.fg)
write_color("cursor_bg", theme.cursor_bg)
write_color("cursor_fg", theme.cursor_fg)
write_color("selection_bg", theme.selection_bg)
write_color("selection_fg", theme.selection_fg)
write_color("link_color", theme.link_color)
output.write("colorscheme_ansi_colors=(\n")
for color in theme.ansi_colors:
output.write(" {}\n".format(color.hex))
output.write(")\n")
class ThemeGeneratorVim(ThemeGenerator):
def file_name(self) -> str:
return "vim.vim"
def generate(self, theme: Theme, output: TextIO) -> None:
namespace = "dotfiles_colorscheme_"
output.write("let {}name = '{}'\n".format(namespace, theme.name))
output.write("let {}base16_name = '{}'\n".format(namespace, theme.base16_name))
output.write("let {}base16_colors = [\n".format(namespace))
for gui_color, cterm_color in zip(theme.base16_colors, ANSI_TO_BASE16_MAPPING):
output.write(
"\\ {{'gui': '{}', 'cterm': '{:02}'}},\n".format(gui_color.css_hex, cterm_color)
)
output.write("\\ ]\n")
namespace = "terminal_color_"
output.write("let {}background = '{}'\n".format(namespace, theme.bg.css_hex))
output.write("let {}foreground = '{}'\n".format(namespace, theme.fg.css_hex))
for index, color in enumerate(theme.ansi_colors[:16]):
output.write("let {}{} = '{}'\n".format(namespace, index, color.css_hex))
class ThemeGeneratorSetvtrgb(ThemeGenerator):
# default setvtrgb config:
# 0,170,0,170,0,170,0,170,85,255,85,255,85,255,85,255
# 0,0,170,85,0,0,170,170,85,85,255,255,85,85,255,255
# 0,0,0,0,170,170,170,170,85,85,85,85,255,255,255,255
def file_name(self) -> str:
return "setvtrgb.txt"
def generate(self, theme: Theme, output: TextIO) -> None:
for i in range(3):
output.write(",".join(str(color[i]) for color in theme.ansi_colors[:16]))
output.write("\n")
class ThemeGeneratorXfceTerminal(ThemeGenerator):
def file_name(self) -> str:
return "xfce4-terminal.theme"
def generate(self, theme: Theme, output: TextIO) -> None:
output.write("[Scheme]\n")
output.write("Name=dmitmel's dotfiles colorscheme\n")
output.write("ColorForeground={}\n".format(theme.fg.css_hex))
output.write("ColorBackground={}\n".format(theme.bg.css_hex))
output.write("ColorCursorUseDefault=FALSE\n")
output.write("ColorCursorForeground={}\n".format(theme.cursor_fg.css_hex))
output.write("ColorCursor={}\n".format(theme.cursor_bg.css_hex))
output.write("ColorSelectionUseDefault=FALSE\n")
output.write("ColorSelection={}\n".format(theme.selection_fg.css_hex))
output.write("ColorSelectionBackground={}\n".format(theme.selection_bg.css_hex))
output.write("TabActivityColor={}\n".format(theme.base16_colors[0x8].css_hex))
output.write("ColorBoldUseDefault=TRUE\n")
output.write(
"ColorPalette={}\n".format(";".join(color.css_hex for color in theme.ansi_colors))
)
class ThemeGeneratorVscode(ThemeGenerator):
def file_name(self) -> str:
return "vscode-colorCustomizations.json"
def generate(self, theme: Theme, output: TextIO) -> None:
ANSI_COLOR_NAMES = [
"Black",
"Red",
"Green",
"Yellow",
"Blue",
"Magenta",
"Cyan",
"White",
]
colors: Dict[str, str] = {
"terminal.background": theme.bg.css_hex,
"terminal.foreground": theme.fg.css_hex,
"terminal.selectionBackground": theme.selection_bg.css_hex,
"terminalCursor.background": theme.cursor_fg.css_hex,
"terminalCursor.foreground": theme.cursor_bg.css_hex,
}
for is_bright in [False, True]:
for color_index, color_name in enumerate(ANSI_COLOR_NAMES):
color = theme.ansi_colors[color_index + int(is_bright) * len(ANSI_COLOR_NAMES)]
colors["terminal.ansi" + ("Bright" if is_bright else "") + color_name] = color.css_hex
json.dump(colors, output, ensure_ascii=False, indent=2)
output.write("\n")
class ThemeGeneratorIterm(ThemeGenerator):
def file_name(self) -> str:
return "iterm.itermcolors"
def generate(self, theme: Theme, output: TextIO) -> None:
output.write('<?xml version="1.0" encoding="UTF-8"?>\n')
output.write(
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
)
output.write('<plist version="1.0">\n')
output.write("<dict>\n")
def write_color(key_name, color):
r, g, b = (float(component) / 0xff for component in color)
output.write(" <key>{} Color</key>\n".format(key_name))
output.write(" <dict>\n")
output.write(" <key>Color Space</key>\n")
output.write(" <string>sRGB</string>\n")
output.write(" <key>Red Component</key>\n")
output.write(" <real>{}</real>\n".format(r))
output.write(" <key>Green Component</key>\n")
output.write(" <real>{}</real>\n".format(g))
output.write(" <key>Blue Component</key>\n")
output.write(" <real>{}</real>\n".format(b))
output.write(" </dict>\n")
write_color("Background", theme.bg)
write_color("Foreground", theme.fg)
write_color("Bold", theme.fg)
write_color("Cursor", theme.cursor_bg)
write_color("Cursor Text", theme.cursor_fg)
write_color("Selection Color", theme.selection_bg)
write_color("Selected Text Color", theme.selection_fg)
for index, color in enumerate(theme.ansi_colors[:16]):
write_color("Ansi " + str(index), color)
write_color("Link", theme.link_color)
output.write("</dict>\n")
output.write("</plist>\n")
class ThemeGeneratorCssVariables(ThemeGenerator):
def file_name(self) -> str:
return "variables.css"
def generate(self, theme: Theme, output: TextIO) -> None:
output.write(":root {\n")
for var_name, color in theme.css_variables.items():
output.write(" --dotfiles-colorscheme-{}: {};\n".format(var_name, color.css_hex))
output.write("}\n")
class ThemeGeneratorScss(ThemeGenerator):
def file_name(self) -> str:
return "_colorscheme.scss"
def generate(self, theme: Theme, output: TextIO) -> None:
output.write("$is-dark: {};\n".format("true" if theme.is_dark else "false"))
for var_name, color in theme.css_variables.items():
output.write("${}: {};\n".format(var_name, color.css_hex))
output.write("$base: ({});\n".format(", ".join(c.css_hex for c in theme.base16_colors)))
output.write("$ansi: ({});\n".format(", ".join(c.css_hex for c in theme.ansi_colors)))
class ThemeGeneratorPrismJs(ThemeGenerator):
def file_name(self) -> str:
return "prismjs-theme.css"
def generate(self, theme: Theme, output: TextIO) -> None:
with open(os.path.join(__dir__, "prismjs-theme-src.css")) as src_file:
src_css = src_file.read()
for var_name, color in theme.css_variables.items():
src_css = src_css.replace("var(--dotfiles-colorscheme-{})".format(var_name), color.css_hex)
output.write(src_css)
def main() -> None:
theme: Theme = MyTheme()
generators: List[ThemeGenerator] = [
ThemeGeneratorKitty(),
ThemeGeneratorTermux(),
ThemeGeneratorZsh(),
ThemeGeneratorVim(),
ThemeGeneratorSetvtrgb(),
ThemeGeneratorXfceTerminal(),
ThemeGeneratorVscode(),
ThemeGeneratorIterm(),
ThemeGeneratorCssVariables(),
ThemeGeneratorScss(),
ThemeGeneratorPrismJs(),
]
out_dir = os.path.join(__dir__, "out")
os.makedirs(out_dir, exist_ok=True)
for generator in generators:
with open(os.path.join(out_dir, generator.file_name()), "w") as output_file:
generator.generate(theme, output_file)
if __name__ == "__main__":
main()

View file

@ -119,4 +119,3 @@
.token.rule {
color: #cc99cc;
}

View file

@ -1,12 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
import os
with open(os.path.join(os.path.dirname(__file__), "prismjs-theme-src.css")) as f:
css_src = f.read()
for var_name, color in theme.css_variables.items():
css_src = css_src.replace("var(--{}{})".format(theme.css_variables_prefix, var_name), color)
print(css_src)

View file

@ -1,11 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
# default setvtrgb config:
# 0,170,0,170,0,170,0,170,85,255,85,255,85,255,85,255
# 0,0,170,85,0,0,170,170,85,85,255,255,85,85,255,255
# 0,0,0,0,170,170,170,170,85,85,85,85,255,255,255,255
for i in range(3):
print(",".join([str(int(color[2 * i + 1:2 * i + 3], 16)) for color in theme.ansi_colors[:16]]))

View file

@ -1,14 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
def print_color(key_name, color):
print("{}={}".format(key_name, color))
print_color("background", theme.bg)
print_color("foreground", theme.fg)
print_color("cursor", theme.cursor_bg)
for index, color in enumerate(theme.ansi_colors[:16]):
print_color("color" + str(index), color)

View file

@ -1,9 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
print(":root {")
for var_name, color in theme.css_variables.items():
print(" --{}{}: {};".format(theme.css_variables_prefix, var_name, color))
print("}")

View file

@ -1,22 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
print("let dotfiles_colorscheme_name = '{}'".format(theme.name))
print("let dotfiles_colorscheme_base16_name = '{}'".format(theme.base16_name))
print("let dotfiles_colorscheme_base16_colors = [")
gui_to_cterm_mapping = [0, 18, 19, 8, 20, 7, 21, 15, 1, 16, 3, 2, 6, 4, 5, 17]
for colors_pair in zip(theme.base16_colors[:16], gui_to_cterm_mapping):
print("\\ {{'gui': '{}', 'cterm': '{:>02}'}},".format(*colors_pair))
print("\\ ]")
def print_terminal_color(key_name, color):
print("let terminal_color_{} = '{}'".format(key_name, color))
print_terminal_color("background", theme.bg)
print_terminal_color("foreground", theme.fg)
for index, color in enumerate(theme.ansi_colors[:16]):
print_terminal_color(str(index), color)

View file

@ -1,31 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
import json
ANSI_COLOR_NAMES = [
"Black",
"Red",
"Green",
"Yellow",
"Blue",
"Magenta",
"Cyan",
"White",
]
colors = {
"terminal.background": theme.bg,
"terminal.foreground": theme.fg,
"terminal.selectionBackground": theme.selection_bg,
"terminalCursor.background": theme.cursor_fg,
"terminalCursor.foreground": theme.cursor_bg,
}
for color_brightness in [False, True]:
for color_index, color_name in enumerate(ANSI_COLOR_NAMES):
color = theme.ansi_colors[color_index + int(color_brightness) * len(ANSI_COLOR_NAMES)]
colors["terminal.ansi" + ("Bright" if color_brightness else "") + color_name] = color
print(json.dumps(colors, ensure_ascii=False, indent=2))

View file

@ -1,18 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
print("[Scheme]")
print("Name=dmitmel's dotfiles colorscheme")
print("ColorForeground={}".format(theme.fg))
print("ColorBackground={}".format(theme.bg))
print("ColorCursorUseDefault=FALSE")
print("ColorCursorForeground={}".format(theme.cursor_fg))
print("ColorCursor={}".format(theme.cursor_bg))
print("ColorSelectionUseDefault=FALSE")
print("ColorSelection={}".format(theme.selection_fg))
print("ColorSelectionBackground={}".format(theme.selection_bg))
print("TabActivityColor={}".format(theme.ansi_colors[1]))
print("ColorBoldUseDefault=TRUE")
print("ColorPalette={}".format(";".join(theme.ansi_colors)))

View file

@ -1,19 +0,0 @@
#!/usr/bin/env python3
import _theme as theme
for attr in [
"bg",
"fg",
"cursor_bg",
"cursor_fg",
"selection_bg",
"selection_fg",
"link_color",
]:
color = getattr(theme, attr)
print("colorscheme_{}={}".format(attr, color[1:]))
print("colorscheme_ansi_colors=(")
for color in theme.ansi_colors:
print(" {}".format(color[1:]))
print(")")

View file

@ -21,7 +21,7 @@
// <https://github.com/primer/css/blob/63764f7edd59c5f4949c91e5373471aa8b0d4865/src/base/normalize.scss>
@use '../node_modules/normalize.css/normalize.css';
@use '../../../colorschemes/out/colorscheme.scss';
@use '../../../colorschemes/out/_colorscheme.scss';
////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION CONSTANTS AND FUNCTIONS