1
Fork 0

Write parser for lens configs

This commit is contained in:
prescientmoon 2024-02-22 13:11:07 +01:00
parent 6dff8afead
commit c769528092
Signed by: prescientmoon
SSH key fingerprint: SHA256:UUF9JT2s8Xfyv76b8ZuVL7XrmimH4o49p4b+iexbVH4
9 changed files with 540 additions and 31 deletions

View file

@ -1,55 +1,62 @@
physical
block
0 1
1 0.5
2 0
3 0.5
4 1
key 0 1
key 1 0.5
key 2 0
key 3 0.5
key 4 1
end
block
place 0 0
place 7 0
end
place 0 0
place 0 1
place 0 2
block
0 0
1 0
key 0 0
key 1 0
end
place 3.5 4.5 0.2617993878 4 5
place 6.5 4.5 -0.2617993878 8 5
section
keyboard
action 🟥 🌈 sticky-switch red
action 🟦 🌈 sticky-switch blue
action 🟪 ⚔️ sticky-switch purple
action 🟥 🌈 sticky-switch red
action 🟦 🌈 sticky-switch blue
action 🟪 ⚔️ sticky-switch purple
layergroup
layer main center
Q W F P B J L U Y :
A R S T G M N E I O
X C D V Z K H , . '
🟥 ␣ ⇧ 🟦
end
layer red topright #0b00d9
1 2 3 4 ⚔️ 🏠 ⏬ ⏫ end 🗑️
1 2 3 4 ⚔️ ⏪ ⏬ ⏫ ⏩ 🗑️
5 6 7 8 ⚔️ ◄ ▼ ▲ ► ⚔️
9 0 ⚔️ ⚔️ ⚔️ ⚔️ ⚔️ ⚔️ ⚔️ ⚔️
⚔️ ⚔️ ⚔️ 🟪
end
layer blue topleft #b80034
! @ [ ( % ^ & * ~ `
< { ] ) ? - _ / = ;
> } $ ? ⚔️ — | \ + "
🟪 ⚔️ ⚔️ ⚔️
end
layer purple bottomleft #660099
f1 f2 f3 f4 f5 😱 copy ⏩ 🔊 🔆
f6 f7 f8 f9 f10 ↩️ 📋 ⏯️ 🔉 🔅
f11 f12 f4 ⚔️ ⚔️ 🎮 ✂️ ⏪ 🔇 ⚔️
⚔️ ⚔️ ⚔️ ⚔️
end
section
columns 2

View file

@ -3,15 +3,23 @@ workspace:
layout-lens:
path: ./
dependencies:
- aff
- colors
- console
- debug
- debugged
- effect
- maybe
- node-fs
- prelude
- string-parsers
- strings
- tuples
- unordered-collections
test_dependencies: []
build_plan:
- aff
- arraybuffer-types
- arrays
- bifunctors
- colors
@ -20,6 +28,7 @@ workspace:
- contravariant
- control
- datetime
- debug
- debugged
- distributive
- effect
@ -29,20 +38,30 @@ workspace:
- exists
- fixed-points
- foldable-traversable
- foreign
- functions
- functors
- gen
- identity
- integers
- invariant
- js-date
- lazy
- lists
- maybe
- newtype
- node-buffer
- node-event-emitter
- node-fs
- node-path
- node-streams
- nonempty
- now
- nullable
- numbers
- ordered-collections
- orders
- parallel
- partial
- prelude
- profunctor
@ -50,6 +69,7 @@ workspace:
- refs
- safe-coerce
- st
- string-parsers
- strings
- tailrec
- transformers
@ -544,6 +564,33 @@ workspace:
git: https://github.com/mateiadrielrafael/purescript-debugged.git
ref: 0d5a4149279129f10c8fe2a3ef280b9fde4d5116
packages:
aff:
type: registry
version: 7.1.0
integrity: sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU=
dependencies:
- arrays
- bifunctors
- control
- datetime
- effect
- either
- exceptions
- foldable-traversable
- functions
- maybe
- newtype
- parallel
- prelude
- refs
- tailrec
- transformers
- unsafe-coerce
arraybuffer-types:
type: registry
version: 3.0.2
integrity: sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA=
dependencies: []
arrays:
type: registry
version: 7.3.0
@ -637,6 +684,13 @@ packages:
- partial
- prelude
- tuples
debug:
type: registry
version: 6.0.2
integrity: sha256-vmkYFuXYuELBzeauvgHG6E6Kf/Hp1dAnxwE9ByHfwSg=
dependencies:
- functions
- prelude
debugged:
type: git
url: https://github.com/mateiadrielrafael/purescript-debugged.git
@ -742,6 +796,20 @@ packages:
- orders
- prelude
- tuples
foreign:
type: registry
version: 7.0.0
integrity: sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA=
dependencies:
- either
- functions
- identity
- integers
- lists
- maybe
- prelude
- strings
- transformers
functions:
type: registry
version: 6.0.0
@ -805,6 +873,17 @@ packages:
dependencies:
- control
- prelude
js-date:
type: registry
version: 8.0.0
integrity: sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo=
dependencies:
- datetime
- effect
- exceptions
- foreign
- integers
- now
lazy:
type: registry
version: 6.0.0
@ -847,6 +926,70 @@ packages:
dependencies:
- prelude
- safe-coerce
node-buffer:
type: registry
version: 9.0.0
integrity: sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4=
dependencies:
- arraybuffer-types
- effect
- maybe
- nullable
- st
- unsafe-coerce
node-event-emitter:
type: registry
version: 3.0.0
integrity: sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w=
dependencies:
- effect
- either
- functions
- maybe
- nullable
- prelude
- unsafe-coerce
node-fs:
type: registry
version: 9.1.0
integrity: sha256-TzhvGdrwcM0bazDvrWSqh+M/H8GKYf1Na6aGm2Qg4+c=
dependencies:
- datetime
- effect
- either
- enums
- exceptions
- functions
- integers
- js-date
- maybe
- node-buffer
- node-path
- node-streams
- nullable
- partial
- prelude
- strings
- unsafe-coerce
node-path:
type: registry
version: 5.0.0
integrity: sha256-pd82nQ+2l5UThzaxPdKttgDt7xlsgIDLpPG0yxDEdyE=
dependencies:
- effect
node-streams:
type: registry
version: 9.0.0
integrity: sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ=
dependencies:
- aff
- effect
- either
- exceptions
- node-buffer
- node-event-emitter
- nullable
- prelude
nonempty:
type: registry
version: 7.0.0
@ -858,6 +1001,21 @@ packages:
- prelude
- tuples
- unfoldable
now:
type: registry
version: 6.0.0
integrity: sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY=
dependencies:
- datetime
- effect
nullable:
type: registry
version: 6.0.0
integrity: sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o=
dependencies:
- effect
- functions
- maybe
numbers:
type: registry
version: 9.0.1
@ -888,6 +1046,22 @@ packages:
dependencies:
- newtype
- prelude
parallel:
type: registry
version: 7.0.0
integrity: sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o=
dependencies:
- control
- effect
- either
- foldable-traversable
- functors
- maybe
- newtype
- prelude
- profunctor
- refs
- transformers
partial:
type: registry
version: 4.0.0
@ -941,6 +1115,21 @@ packages:
- prelude
- tailrec
- unsafe-coerce
string-parsers:
type: registry
version: 8.0.0
integrity: sha256-9ATYh0S54ERoR+uhkCM59wBRvW/6zv6geHJ0TmcI644=
dependencies:
- arrays
- bifunctors
- control
- either
- foldable-traversable
- lists
- maybe
- prelude
- strings
- tailrec
strings:
type: registry
version: 6.0.1

View file

@ -7,8 +7,13 @@ package:
- tuples
- maybe
- debugged
- debug
- colors
- unordered-collections
- string-parsers
- node-fs
- aff
- strings
test:
main: Test.Main
dependencies: []

View file

@ -10,6 +10,9 @@ derive instance Generic LayerVisualPosition _
instance Debug LayerVisualPosition where
debug = genericDebug
instance Show LayerVisualPosition where
show = genericShow
instance Hashable LayerVisualPosition where
hash Center = 0
hash TopLeft = 1

View file

@ -38,6 +38,9 @@ newtype RawLayer = RawLayer
, keys :: Array RawKeySymbol
}
layerName :: RawLayer -> String
layerName (RawLayer { name }) = name
data RawElement
= RawLayerGroup (HashMap LayerVisualPosition RawLayer)
| RawChordGroup (Array RawChord)
@ -47,6 +50,9 @@ newtype RawSection = RawSection
, elements :: Array RawElement
}
sectionElements :: RawSection -> Array RawElement
sectionElements (RawSection { elements }) = elements
data RawActionDisplay
= DisplaySymbol RawKeySymbol
| DisplayLayerColor
@ -56,15 +62,14 @@ data RawActionEffect
| StickyLayerSwitch String
newtype RawAction = RawAction
{ name :: String
, visualSymbol :: RawActionDisplay
{ display :: RawActionDisplay
, effect :: RawActionEffect
}
newtype RawConfig = RawConfig
{ physical :: RawPhysical
, actions :: Array RawAction
, sections :: RawSection
, actions :: HashMap String RawAction
, sections :: Array RawSection
}
derive instance Eq RawPhysicalActionStep

View file

@ -1,10 +1,17 @@
module Main where
import Prelude
import LayoutLens.Prelude
import Effect (Effect)
import Effect.Console (log)
import LayoutLens.Parser (parseConfig)
import Node.Encoding (Encoding(..))
import Node.FS.Aff (readTextFile)
main :: Effect Unit
main = do
log "🍝"
main = launchAff_ do
file <- readTextFile UTF8 "../keyboards/qmk/ferris-sweep/config.lens"
case parseConfig file of
Left err -> log err
Right result -> log
$ prettyPrintWith
defaultPrettyPrintOptions { maxDepth = Nothing }
$ debug result

264
layout-lens/src/Parser.purs Normal file
View file

@ -0,0 +1,264 @@
module LayoutLens.Parser (parseConfig) where
import LayoutLens.Prelude hiding (string)
import Data.Array as Array
import Data.HashMap as HM
import Data.HashSet as HS
import Data.Int as Int
import Data.Number as Number
import Data.String.CodeUnits as String
import LayoutLens.Data.Config (LayerVisualPosition(..))
import LayoutLens.Data.RawConfig (RawAction(..), RawActionDisplay(..), RawActionEffect(..), RawChord(..), RawConfig(..), RawElement(..), RawKeySymbol(..), RawLayer(..), RawPhysical(..), RawPhysicalActionStep(..), RawPhysicalStep(..), RawSection(..), layerName, sectionElements)
import LayoutLens.Data.Vec2 (Radians(..), Vec2(..))
import Safe.Coerce (coerce)
import StringParser (Parser, printParserError, runParser)
import StringParser as P
-- {{{ Base combinators
singleNewline :: Parser Unit
singleNewline = void $ flip P.withError "failed to match single newline" $ P.regex "\n"
iws :: Parser Unit
iws = void $ flip P.withError "failed to match one or more inline whitespace" $ P.regex "[ \t]+"
oiws :: Parser Unit
oiws = void $ flip P.withError "failed to match zero or more inline whitespace" $ P.regex "[ \t]*"
ows :: Parser Unit
ows = void $ flip P.withError "failed to match zero or more whitespace" $ P.regex "[ \t\n]*"
ws :: Parser Unit
ws = void $ flip P.withError "failed to match one or more whitespace" $ P.regex "[ \t\n]+"
newline :: Parser Unit
newline = void $ P.many1 (P.try $ (oiws *> singleNewline)) *> oiws
manyLines :: forall a. Parser a -> Parser (Array a)
manyLines p = Array.fromFoldable <$> P.many (p <* ows)
tok :: forall a. Parser a -> Parser a
tok p = iws *> p
number :: Parser Number
number = do
string <- flip P.withError "failed to match real" $ P.regex "[-+]?[0-9]*\\.?[0-9]+"
case Number.fromString string of
Just num -> pure num
Nothing -> P.fail $ "Invalid number " <> string
nat :: Parser Int
nat = do
string <- flip P.withError "failed to match natural" $ P.regex "[0-9]+"
case Int.fromString string of
Just num -> pure num
Nothing -> P.fail $ "Invalid natural " <> string
vec2 :: Parser Vec2
vec2 = Vec2 <$> (iws *> number) <*> (iws *> number)
radians :: Parser Radians
radians = Radians <$> (iws *> number)
name :: Parser String
name = ows *> P.try do
result <- P.regex "\\S+"
when (Array.elem result kws) $
P.fail "Names cannot be keywords"
pure result
where
kws = [ "layergroup", "chordgroup" ]
color :: Parser Color
color = do
string <- flip P.withError "failed to match hexstring" $ P.regex "#[0-9a-fA-F]{6}"
case fromHexString string of
Just color -> pure color
Nothing -> P.fail $ "Invalid color " <> string
string :: String -> Parser Unit
string s = oiws <* P.string s
noDuplicates :: String -> Array String -> Parser Unit
noDuplicates what arr =
void $
Array.foldM
( \prev name -> do
when (HS.member name prev) do
P.fail $ what <> " " <> name <> " defined multiple times"
pure $ HS.insert name prev
)
HS.empty
arr
-- }}}
physical :: Parser RawPhysical
physical = do
string "physical" *> newline
RawPhysical <$> manyLines (block <|> (PhysicalAction <$> actionStep))
where
block :: Parser RawPhysicalStep
block = do
string "block" *> newline
steps <- manyLines actionStep
string "end"
pure $ Block steps
actionStep :: Parser RawPhysicalActionStep
actionStep = place <|> point
place :: Parser RawPhysicalActionStep
place = flip P.withError "failed to parse 'place' command" do
string "place"
offset <- vec2
rotateBy /\ rotateAround <- P.option (Radians 0.0 /\ offset) do
angle <- radians
around <- P.option offset vec2
pure $ angle /\ around
pure $ Place { offset, rotateBy, rotateAround }
point :: Parser RawPhysicalActionStep
point = do
string "key"
position <- vec2
arguments <- Array.fromFoldable <$> P.many (iws *> number)
let size = Vec2 1.0 1.0
let rotateBy = Radians 0.0
let rotateAround = position
case arguments of
[] -> pure $ Point { position, size, rotateBy, rotateAround }
[ angle ] -> pure $ Point { position, size, rotateAround, rotateBy: Radians angle }
[ sx, sy ] -> pure $ Point { position, rotateBy, rotateAround, size: Vec2 sx sy }
[ sx, sy, angle ] -> pure $ Point
{ position
, rotateAround
, size: Vec2 sx sy
, rotateBy: Radians angle
}
[ sx, sy, angle, rx, ry ] -> pure $ Point
{ position
, size: Vec2 sx sy
, rotateBy: Radians angle
, rotateAround: Vec2 rx ry
}
_ -> P.fail "Too many arguments provided to point"
layer :: Parser (LayerVisualPosition /\ RawLayer)
layer = do
string "layer"
layerName <- tok name
position <- tok $ oneOf
[ string "center" $> Center
, string "topleft" $> TopLeft
, string "topright" $> TopRight
, string "bottomleft" $> BottomLeft
, string "bottomright" $> BottomRight
]
textColor <- P.optionMaybe $ tok color
newline
keys <- Array.fromFoldable
<$> P.many1Till
(rawKeySymbol <* ws)
(string "end")
pure $ position /\ RawLayer { name: layerName, keys, textColor }
layergroup :: Parser RawElement
layergroup = do
string "layergroup" *> newline
layers <- manyLines layer
noDuplicates "Layer" $ (show <<< fst) <$> layers
pure $ RawLayerGroup $ coerce $ Array.foldMap
(\(name /\ value) -> HM.singleton name $ wrapInto @(First RawLayer) value)
layers
chord :: Parser RawChord
chord = do
from <- Array.fromFoldable <$> P.manyTill
(rawKeySymbol <* iws)
(P.string "=>")
to <- tok $ Array.fromFoldable <$> P.manyTill
(rawKeySymbol <* iws)
(P.lookAhead color)
fill <- color
fontSizeModifier <- P.option 1.0 $ tok number
pure $ RawChord { from, to, fill, fontSizeModifier }
chordgroup :: Parser RawElement
chordgroup = do
string "chordgroup" *> newline
c <- RawChordGroup <$> manyLines chord
pure c
type NamedRawAction = String /\ RawAction
rawKeySymbol :: Parser RawKeySymbol
rawKeySymbol = RawKeySymbol <$> name
action :: Parser NamedRawAction
action = do
string "action"
actionName <- tok name
display <- tok $ oneOf
[ DisplayLayerColor <$ string "🌈"
, DisplaySymbol <$> rawKeySymbol
]
effect <- tok $ oneOf
[ string "switch" *> (LayerSwitch <$> tok name)
, string "sticky-switch" *> (StickyLayerSwitch <$> tok name)
]
pure $ actionName /\ RawAction { display, effect }
section :: Parser (Array NamedRawAction /\ RawSection)
section = do
string "section" *> newline
actions /\ columnCounts /\ elements <- map fold $ manyLines $ oneOf
[ action <#> \action -> [ action ] /\ [] /\ []
, parseColumns <#> \amount -> [] /\ [ amount ] /\ []
, layergroup <|> chordgroup <#> \element -> [] /\ [] /\ [ element ]
]
columns <- case columnCounts of
[] -> pure 1
[ single ] -> pure single
_ -> P.fail $ "Column count defined multiple times " <> show columnCounts
pure $ actions /\ RawSection { columns, elements }
where
parseColumns :: Parser Int
parseColumns = P.string "columns" *> tok nat
config :: Parser RawConfig
config = do
physical <- physical
sections <- ows *> manyLines section <* ows <* P.eof
sections
>>= fst
<#> fst
# noDuplicates "Action"
sections
<#> snd
>>= sectionElements
>>= case _ of
RawLayerGroup layers -> layerName <$> HM.values layers
RawChordGroup _ -> []
# noDuplicates "Layer"
pure $ RawConfig
{ physical
, sections: sections <#> snd
, actions: sections
>>= fst
# Array.foldMap
(\(name /\ action) -> HM.singleton name $ wrapInto @(First _) action)
# coerce
}
parseConfig :: String -> Either String RawConfig
parseConfig input = case runParser config input of
Left err -> Left $ fold [ printParserError err, "\n", String.slice (err.pos) (err.pos + 30) input ]
Right result -> Right result

View file

@ -12,18 +12,47 @@ module LayoutLens.Prelude
, module Data.HashMap
, module Data.HashSet
, module Data.Hashable
, module Control.Monad.Reader
, module Control.Alternative
, module Data.Foldable
, module Data.Show.Generic
, module Data.Either
, module Effect.Aff
, module Safe.Coerce
, module Data.Newtype
, module Data.Semigroup.First
, wrapInto
, unimplemented
) where
import Prelude
import Data.Maybe (Maybe(..), fromJust, fromMaybe, fromMaybe', isJust, isNothing, maybe, maybe', optional)
import Data.Tuple (Tuple(..), curry, fst, snd, swap, uncurry)
import Data.Tuple.Nested (type (/\), T10, T11, T2, T3, T4, T5, T6, T7, T8, T9, Tuple1, Tuple10, Tuple2, Tuple3, Tuple4, Tuple5, Tuple6, Tuple7, Tuple8, Tuple9, curry1, curry10, curry2, curry3, curry4, curry5, curry6, curry7, curry8, curry9, get1, get10, get2, get3, get4, get5, get6, get7, get8, get9, over1, over10, over2, over3, over4, over5, over6, over7, over8, over9, tuple1, tuple10, tuple2, tuple3, tuple4, tuple5, tuple6, tuple7, tuple8, tuple9, uncurry1, uncurry10, uncurry2, uncurry3, uncurry4, uncurry5, uncurry6, uncurry7, uncurry8, uncurry9, (/\))
import Effect (Effect, forE, foreachE, untilE, whileE)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Class.Console (clear, error, errorShow, group, groupCollapsed, groupEnd, grouped, info, infoShow, log, logShow, time, timeEnd, timeLog, warn, warnShow)
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), NoConstructors, Product(..), Sum(..), from, repOf, to)
import Data.Debug (class Debug, class DebugRowList, class GenericDebug, class GenericDebugArgs, DiffOptions, PrettyPrintOptions, Repr, ReprDelta, array, assoc, boolean, char, collection, constructor, debug, debugRowList, defaultDiffOptions, defaultPrettyPrintOptions, diff, diffRepr, diffReprWith, genericDebug, genericDebug', genericDebugArgs, int, number, opaque, opaqueLiteral, opaque_, prettyPrint, prettyPrintDelta, prettyPrintDeltaWith, prettyPrintWith, record, string)
import Color (Color, ColorSpace(..), Interpolator, black, brightness, complementary, contrast, cssStringHSLA, cssStringRGBA, darken, desaturate, distance, fromHexString, fromInt, graytone, hsl, hsla, hsv, hsva, isLight, isReadable, lab, lch, lighten, luminance, mix, mixCubehelix, rgb, rgb', rgba, rgba', rotateHue, saturate, textColor, toGray, toHSLA, toHSVA, toHexString, toLCh, toLab, toRGBA, toRGBA', toXYZ, white, xyz)
import Control.Alternative (class Alt, class Alternative, empty, (<|>))
import Control.Monad.Reader (Reader, ReaderT, runReader, runReaderT, ask, asks, local)
import Data.Debug (class Debug, class DebugRowList, class GenericDebug, class GenericDebugArgs, DiffOptions, PrettyPrintOptions, Repr, ReprDelta, array, assoc, boolean, char, collection, constructor, debug, debugRowList, defaultDiffOptions, defaultPrettyPrintOptions, diff, diffRepr, diffReprWith, genericDebug, genericDebug', genericDebugArgs, opaque, opaqueLiteral, opaque_, prettyPrint, prettyPrintDelta, prettyPrintDeltaWith, prettyPrintWith, record, string)
import Data.Either (Either(..), blush, choose, either, fromLeft, fromLeft', fromRight, fromRight', hush, isLeft, isRight, note, note')
import Data.Foldable (class Foldable, all, and, any, elem, find, findMap, fold, foldM, foldMap, foldMapDefaultL, foldMapDefaultR, foldl, foldlDefault, foldr, foldrDefault, for_, indexl, indexr, intercalate, length, lookup, maximum, maximumBy, minimum, minimumBy, notElem, null, oneOf, oneOfMap, or, product, sequence_, sum, surround, surroundMap, traverse_)
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), NoConstructors, Product(..), Sum(..), from, repOf, to)
import Data.HashMap (HashMap)
import Data.HashSet (HashSet)
import Data.Hashable (class Hashable)
import Data.Maybe (Maybe(..), fromJust, fromMaybe, fromMaybe', isJust, isNothing, maybe, maybe', optional)
import Data.Newtype (class Newtype, wrap)
import Data.Show.Generic (genericShow)
import Data.Tuple (Tuple(..), curry, fst, snd, swap, uncurry)
import Data.Tuple.Nested (type (/\), T10, T11, T2, T3, T4, T5, T6, T7, T8, T9, Tuple1, Tuple10, Tuple2, Tuple3, Tuple4, Tuple5, Tuple6, Tuple7, Tuple8, Tuple9, curry1, curry10, curry2, curry3, curry4, curry5, curry6, curry7, curry8, curry9, get1, get10, get2, get3, get4, get5, get6, get7, get8, get9, over1, over10, over2, over3, over4, over5, over6, over7, over8, over9, tuple1, tuple10, tuple2, tuple3, tuple4, tuple5, tuple6, tuple7, tuple8, tuple9, uncurry1, uncurry10, uncurry2, uncurry3, uncurry4, uncurry5, uncurry6, uncurry7, uncurry8, uncurry9, (/\))
import Effect (Effect, forE, foreachE, untilE, whileE)
import Effect.Aff (Aff, BracketConditions, Canceler(..), Error, Fiber, Milliseconds(..), ParAff, apathize, attempt, bracket, cancelWith, catchError, delay, effectCanceler, error, fiberCanceler, finally, forkAff, generalBracket, invincible, joinFiber, killFiber, launchAff, launchAff_, launchSuspendedAff, makeAff, message, never, nonCanceler, parallel, runAff, runAff_, runSuspendedAff, sequential, supervise, suspendAff, throwError, try)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Class.Console (clear, group, groupCollapsed, groupEnd, grouped, info, infoShow, log, logShow, time, timeEnd, timeLog, warn, warnShow)
import Effect.Exception.Unsafe (unsafeThrow)
import Prim.TypeError (class Warn, Text)
import Safe.Coerce (class Coercible, coerce)
import Data.Semigroup.First (First(..))
unimplemented :: forall a. Warn (Text "unimplemenet") => a
unimplemented = unsafeThrow "unimplemented"
wrapInto :: forall a @t. Newtype t a => a -> t
wrapInto = wrap

View file

@ -4,9 +4,9 @@
set iskeyword+=-
syntax keyword lensKeyword physical section keyboard layer chordgroup block
syntax keyword lensKeyword physical section layergroup layer chordgroup block end
syntax keyword lensAction sticky-switch switch
syntax keyword lensFunction columns place action
syntax keyword lensFunction columns place action key
syntax keyword lensLayerName center topleft topright bottomleft bottomright
syntax match lensComment "\v--.*$"