lib.rasi
A DSL for generating Rofi's RASI theme format from Nix.
#
lib.rasi.isLiteral
Check if the given value is a rasi literal, i.e. an attribute set carrying an
asRasiLiteral attribute as produced by mkLiteral.
Type
isLiteral :: Any -> Bool
#
lib.rasi.isHex
Check if the given value is a string in hex format.
Type
isHex :: Any -> Bool
#
lib.rasi.mkLiteral
Construct a Rasi literal value. When serialized to Rasi, this will be a literal string in the final file with no quotes or special formatting.
Every constructor in this library -- colours, distances, gradients, keywords -- ultimately returns one of these, so a literal is the common currency of the RASI DSL. Use it directly for any syntax the library does not wrap yet.
Type
mkLiteral :: String -> Literal
Examples
mkLiteral "bold"
=> { asRasiLiteral = "bold"; }
toRASI { "*" = { font = mkLiteral "monospace 12"; }; }
=> "* {\n font: monospace 12;\n}\n"
#
lib.rasi.mkMultiLiteral
Construct a literal with multiple components from other values.
Each part is rendered with mkValueString and the results joined with a
single space, which is how RASI writes compound values such as padding,
border widths and border styles. The pad*, border* and borderStyle*
helpers are all thin wrappers over this.
Type
mkMultiLiteral :: [Any] -> Literal
Examples
mkMultiLiteral [ (pixels 4) (pixels 8) ]
=> { asRasiLiteral = "4px 8px"; }
#
lib.rasi.mkValueString
Convert a given value to it's rasi string representation. If the value is a rasi literal
created with mkLiteral, it will be serialized appropriately. Otherwise, the default
lib.generators.mkValueStringDefault converter is used for base types.
Lists become bracketed, comma-separated RASI lists; strings are quoted with
newlines, quotes and backslashes escaped; and a bare integer is taken to mean
pixels, so padding = 8 and padding = pixels 8 render the same.
Type
mkValueString :: Any -> String
Examples
mkValueString (mkLiteral "bold") => "bold"
mkValueString 8 => "8px"
mkValueString "hello" => "\"hello\""
mkValueString [ (mkLiteral "a") (mkLiteral "b") ] => "[a,b]"
#
lib.rasi.hexColor
Construct a colour from a bare hexadecimal string -- no leading #, which
this adds. Any length RASI accepts works (RGB, RGBA, RRGGBB,
RRGGBBAA); aborts if the string contains anything but hex digits.
Written to take the digits alone so a palette value from nix-colors can be passed straight through.
Type
hexColor :: String -> Literal
Examples
hexColor "1e1e2e" => { asRasiLiteral = "#1e1e2e"; }
hexColor config.colorScheme.palette.base00
#
lib.rasi.rgb
Construct an rgb() colour. Each component is rendered with mkValueString,
so integers, percent values and other literals are all accepted.
Type
rgb :: Any -> Any -> Any -> Literal
Examples
rgb 30 30 46
=> { asRasiLiteral = "rgb(30px,30px,46px)"; }
rgb (mkLiteral "30") (mkLiteral "30") (mkLiteral "46")
=> { asRasiLiteral = "rgb(30,30,46)"; }
#
lib.rasi.rgba
Construct an rgba() colour. As with rgb, every component goes through
mkValueString, so a bare integer renders as pixels -- wrap components in
mkLiteral or percent when that is not what you want.
Type
rgba :: Any -> Any -> Any -> Any -> Literal
Examples
rgba (mkLiteral "30") (mkLiteral "30") (mkLiteral "46") (mkLiteral "0.8")
=> { asRasiLiteral = "rgba(30,30,46,0.8)"; }
#
lib.rasi.transparent
The transparent colour keyword.
#
lib.rasi.bold
Text style keywords, for RASI's text-style property: bold, italic,
underline, strikethrough and nostyle (which renders as none).
#
lib.rasi.img
Reference an image by path, as RASI's url("..."). Use imgScale to also
give the scaling mode.
Type
img :: (Path | String) -> Literal
Examples
img ./wallpaper.png
=> { asRasiLiteral = ''url("/nix/store/...-wallpaper.png")''; }
#
lib.rasi.imgScale
Reference an image by path together with a scaling mode -- RASI's
url("...", mode). The mode is rendered with mkValueString, so pass it as
a literal (mkLiteral "both", mkLiteral "width", mkLiteral "height").
Type
imgScale :: (Path | String) -> Any -> Literal
Examples
imgScale ./wallpaper.png (mkLiteral "both")
=> { asRasiLiteral = ''url("/nix/store/...-wallpaper.png", both)''; }
#
lib.rasi.left
Direction keywords, used by properties that take one: left, right, up
and down.
#
lib.rasi.northWest
Compass position keywords, for anchoring and window location: northWest,
north, northEast, east, southEast, south, southWest and west.
The corner names render with a space, e.g. north west.
#
lib.rasi.horizontal
Orientation keywords, for properties such as orientation: horizontal and
vertical.
#
lib.rasi.radians
Construct an angle in radians from a float. Aborts on anything that is not a
float -- write 1.0, not 1. See degrees for the same thing in degrees,
and angle for a bare, unitless value.
Type
radians :: Float -> Literal
Examples
radians 1.57 => { asRasiLiteral = "1.570000rad"; }
#
lib.rasi.degrees
Construct an angle in degrees from a float. Aborts on anything that is not a
float -- write 90.0, not 90.
Type
degrees :: Float -> Literal
Examples
degrees 90.0 => { asRasiLiteral = "90.000000deg"; }
#
lib.rasi.percent
Construct a percentage. Accepts an int or a float and aborts outside
[0,100]. Used both as a distance (a percentage of the parent) and as the
argument to a named colour's divide.
Type
percent :: (Int | Float) -> Literal
Examples
percent 50 => { asRasiLiteral = "50%"; }
colors.aliceblue.divide (percent 50)
#
lib.rasi.angle
Construct a bare, unitless number from a float, for the places RASI wants an angle with no suffix. Aborts on anything that is not a float.
Type
angle :: Float -> Literal
Examples
angle 0.5 => { asRasiLiteral = "0.500000"; }
#
lib.rasi.colors
The named colours RASI understands, as an attribute set keyed by name
(colors.aliceblue, colors.rebeccapurple, ...). The names come from
./named-colors.nix and are all lower case.
Each entry is a literal that also carries a divide function, RASI's
name / value syntax for taking a fraction of a colour. divide renders its
argument with mkValueString, so pass a percent rather than a bare integer
-- a bare integer is read as pixels.
Type
colors :: AttrSet
Examples
colors.aliceblue
=> { asRasiLiteral = "aliceblue"; divide = <lambda>; }
colors.aliceblue.divide (percent 50)
=> { asRasiLiteral = "aliceblue / 50%"; }
#
lib.rasi.dash
Line style keywords, for border styles: dash and solid.
#
lib.rasi.mkDuoCalc
Construct a RASI calc() expression from two operands and an operator. Both
operands are rendered with mkValueString, so they may themselves be
calc() literals and nest.
The calc* helpers below are the named operators; reach for this directly
only for an operator they do not cover.
Type
mkDuoCalc :: Any -> String -> Any -> Literal
Examples
mkDuoCalc (percent 100) "-" (pixels 20)
=> { asRasiLiteral = "calc(100% - 20px)"; }
#
lib.rasi.calcSub
The named binary calc() operators, each lhs -> rhs -> Literal over
mkDuoCalc: calcSub (-), calcAdd (+), calcDiv (/), calcMul
(*), calcMin, calcMax, calcFloor, calcCeil, calcRound and
calcMod (modulo).
Type
calcSub :: Any -> Any -> Literal
Examples
calcSub (percent 100) (pixels 20)
=> { asRasiLiteral = "calc(100% - 20px)"; }
calcDiv (calcSub (percent 100) (pixels 20)) (mkLiteral "2")
=> { asRasiLiteral = "calc(calc(100% - 20px) / 2)"; }
#
lib.rasi.pixels
Distance constructors, one per RASI unit: pixels (px), elements (em),
characters (ch) and millimeters (mm). See also percent for a
distance relative to the parent.
pixels is the unit mkValueString assumes for a bare integer, so
padding = 8 and padding = pixels 8 produce the same output.
Type
pixels :: (Int | Float) -> Literal
Examples
pixels 8 => { asRasiLiteral = "8px"; }
elements 1 => { asRasiLiteral = "1em"; }
#
lib.rasi.linearGradient
Construct a linear gradient function (for use where an image is required).
Inputs
directionOrAngle
: A direction keyword (left, right, up, down) or an angle
(degrees, radians), or null (the default) to leave it to RASI.
stops
: List of { color, value } stops, emitted in order as color, value pairs.
Type
linearGradient :: { directionOrAngle :: (Literal | Null), stops :: [{ color :: Any, value :: Any; }] } -> Literal
Examples
linearGradient {
stops = [
{ color = colors.black; value = percent 0; }
{ color = colors.white; value = percent 100; }
];
}
=> { asRasiLiteral = "linearGradient(black,0%,white,100%)"; }
#
lib.rasi.pad1
Padding constructors, following RASI's CSS-style shorthand by arity:
pad1 v-- all four sides (the identity function, present for symmetry)pad2 topBottom leftRightpad3 top leftRight bottompad4 top right bottom left
Each takes distance values (pixels, elements, percent, ...) and joins
them with mkMultiLiteral.
Type
pad2 :: Any -> Any -> Literal
Examples
pad2 (pixels 4) (pixels 8)
=> { asRasiLiteral = "4px 8px"; }
#
lib.rasi.border1
Border width constructors, the same shorthand-by-arity as the pad* family:
border1 v-- all four sides (identity, present for symmetry)border2 topBottom leftRightborder3 top leftRight bottomborder4 top right bottom left
Use the borderStyle* family to give each width a line style as well.
Type
border2 :: Any -> Any -> Literal
Examples
border4 (pixels 1) (pixels 0) (pixels 1) (pixels 0)
=> { asRasiLiteral = "1px 0px 1px 0px"; }
#
lib.rasi.borderStyle1
Border constructors that pair each width with a line style (solid, dash),
interleaved as RASI expects:
borderStyle1 width style-- all four sidesborderStyle2 topBottom tbStyle leftRight lrStyleborderStyle3 top tStyle leftRight lrStyle bottom bStyleborderStyle4 top tStyle right rStyle bottom bStyle left lStyle
Type
borderStyle1 :: Any -> Any -> Literal
Examples
borderStyle1 (pixels 2) solid
=> { asRasiLiteral = "2px solid"; }
borderStyle2 (pixels 2) solid (pixels 0) dash
=> { asRasiLiteral = "2px solid 0px dash"; }
#
lib.rasi.varDefault
Indirection into a theme variable or the environment. Four constructors, in two pairs:
var name-- reference a theme variable, RASI's@namevarDefault name default-- the same, with a fallback:var(name, default)env name-- reference an environment variable, RASI's${name}envDefault name default-- the same, with a fallback:env(name, default)
The fallback is rendered with mkValueString, so it may be any value this
library produces.
Type
varDefault :: String -> Any -> Literal
Examples
var "background" => { asRasiLiteral = "@background"; }
varDefault "background" (hexColor "1e1e2e")
=> { asRasiLiteral = "var(background, #1e1e2e)"; }
#
lib.rasi.inherited
The inherit keyword, taking the property's value from the parent element.
Named inherited because inherit is a Nix keyword.
#
lib.rasi.default
Cursor keywords, for the cursor property: default, pointer and text.
#
lib.rasi.none
The none keyword, for properties that can be switched off outright.
nostyle is the same literal, named for the text-style group.
#
lib.rasi.toRASI
Generate a RASI configuration file normally used with Rofi. This is the format used for configuration files and themes for rofi.
The document is an attribute set of sections; each section is an attribute
set of properties, whose values are rendered with mkValueString. Section
names are emitted verbatim, so they carry rofi's own selector syntax
("*", "window", "element selected.normal"). Sections and properties
are emitted in attribute order, which for an attribute set means sorted by
name.
Type
toRASI :: AttrSet -> String
Examples
toRASI {
"*" = {
background-color = hexColor "1e1e2e";
text-color = hexColor "cdd6f4";
};
"window" = {
width = percent 40;
padding = pad2 (pixels 8) (pixels 12);
};
}
=>
''
* {
background-color: #1e1e2e;
text-color: #cdd6f4;
}
window {
padding: 8px 12px;
width: 40%;
}
''