Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e5ce626
add primitive `key` type
byorgey Apr 2, 2023
fe4e861
add primitive `key` command
byorgey Apr 2, 2023
47118d0
add `Key` values with parsing+pretty-printing
byorgey Apr 5, 2023
d111812
add placeholder `installKeyHandler` command
byorgey Apr 5, 2023
dbc859c
piloting -> input handler
byorgey Apr 5, 2023
fce993b
add replInputHandler to REPL state
byorgey Apr 5, 2023
df64259
add `inputHandler` field to game state
byorgey Apr 6, 2023
36cf92e
add back piloting mode
byorgey Apr 11, 2023
7ac2f24
WIP: deal with keypresses in input handler mode
byorgey Apr 11, 2023
0926a81
WIP: get basic key handler working
byorgey Apr 12, 2023
5c38cf4
change REPL prompt when key handler is running
byorgey Apr 12, 2023
951497e
add todo, and fix import
byorgey Apr 13, 2023
6c5df04
add `handle` device
byorgey Apr 16, 2023
a5e77d3
use hint line for handler, clean up comments
byorgey Apr 16, 2023
f1d4672
add list of special key names under `swarm generate keys`
byorgey Apr 16, 2023
b6ce2f9
add some key handler examples
byorgey Apr 16, 2023
44b35ca
Merge branch 'main' into feature/input-handler
byorgey Apr 16, 2023
4406960
remove completed todo
byorgey Apr 17, 2023
1c771b9
remove accidentally added file and remove completed todo
byorgey Apr 17, 2023
eba6e87
add `key` and `installKeyHandler` to editor configs
byorgey Apr 17, 2023
62bb1f4
Merge branch 'main' into feature/input-handler
byorgey Apr 17, 2023
ed69f15
fix `hlint` warning
byorgey Apr 17, 2023
6013760
remove redundant parentheses
byorgey Apr 17, 2023
aaf94aa
add a few explanatory comments
byorgey Apr 17, 2023
129b849
fix comment
byorgey Apr 17, 2023
9a4942c
group input handler + hint text
byorgey Apr 22, 2023
7fb3416
Merge branch 'main' into feature/input-handler
byorgey Apr 22, 2023
2df977e
add installed `handle` device to `bridge-building` challenge
byorgey Apr 22, 2023
6cb11bb
Merge branch 'main' into feature/input-handler
byorgey Apr 25, 2023
b3ebc94
remove duplicate `handle` entity, and add `key` + `keyboard` devices
byorgey Apr 25, 2023
f0fc631
WIP: add logging to pilot mode example
byorgey Apr 25, 2023
c595701
update hint string in pilot mode example
byorgey Apr 25, 2023
bf692e7
Merge branch 'main' into feature/input-handler
mergify[bot] Apr 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ cliParser =
subparser . mconcat $
[ command "recipes" (info (pure RecipeGraph) $ progDesc "Output graphviz dotfile of entity dependencies based on recipes")
, command "editors" (info (EditorKeywords <$> editor <**> helper) $ progDesc "Output editor keywords")
, command "keys" (info (pure SpecialKeyNames) $ progDesc "Output list of recognized special key names")
, command "cheatsheet" (info (CheatSheet <$> address <*> cheatsheet <**> helper) $ progDesc "Output nice Wiki tables")
, command "pedagogy" (info (pure TutorialCoverage) $ progDesc "Output tutorial coverage")
]
Expand Down
25 changes: 25 additions & 0 deletions data/entities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1223,3 +1223,28 @@
A nanoscale semiconductor particle with a wide range of
applications.
properties: [portable]

- name: 'key'
display:
attr: gold
char: 'k'
description:
- A versatile item, with uses such as opening
locked doors, entering input, and retrieving stored values.
properties: [portable]

- name: keyboard
display:
attr: device
char: 'K'
description:
- A small device with multiple keys, adapted for your unique anatomy.
- |
`installKeyHandler : text -> (key -> cmd unit) -> cmd unit`
installs a custom handler function that can be activated to
respond to keyboard inputs typed at the REPL.
- |
`key : text -> key` constructs values of type `key`, for
example `key "Down"` or `key "C-S-x"`.
properties: [portable]
capabilities: [handleinput]
11 changes: 11 additions & 0 deletions data/recipes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -829,3 +829,14 @@
- [1, iron plate]
out:
- [1, victrola]

- in:
- [1, iron plate]
out:
- [4, key]

- in:
- [1, board]
- [16, key]
out:
- [1, keyboard]
3 changes: 2 additions & 1 deletion data/scenarios/Challenges/bridge-building.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ robots:
- counter
- dictionary
- grabber
- keyboard
- lambda
- logger
- mirror
Expand Down Expand Up @@ -689,4 +690,4 @@ world:
................../\.....bbbbbbBBBBBBBBBBBBBBBBBBBBBBB.@..@.@
........ccc....../--\......bbbbbbbbBBBBBBBBBBBBBBBq@BB.@.@@.@
......cccccccc..t|ΩMd........bbbbbbbbbbBBBBBBBBBBB@.@.@.@@...
........cccc.....----........................................
........cccc.....----........................................
2 changes: 2 additions & 0 deletions editors/emacs/swarm-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"split"
"charat"
"tochar"
"key"
))
(x-commands '(
"noop"
Expand Down Expand Up @@ -99,6 +100,7 @@
"try"
"swap"
"atomic"
"installkeyhandler"
"teleport"
"as"
"robotnamed"
Expand Down
2 changes: 1 addition & 1 deletion editors/vscode/syntaxes/swarm.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
{
"name": "keyword.other",
"match": "\\b(?i)(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|noop|wait|selfdestruct|move|turn|grab|harvest|place|give|equip|unequip|make|has|equipped|count|drill|build|salvage|reprogram|say|listen|log|view|appear|create|time|scout|whereami|detect|resonate|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|teleport|as|robotnamed|robotnumbered|knows)\\b"
"match": "\\b(?i)(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|key|noop|wait|selfdestruct|move|turn|grab|harvest|place|give|equip|unequip|make|has|equipped|count|drill|build|salvage|reprogram|say|listen|log|view|appear|create|time|scout|whereami|detect|resonate|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|installkeyhandler|teleport|as|robotnamed|robotnumbered|knows)\\b"
}
]
},
Expand Down
20 changes: 20 additions & 0 deletions example/multi-key-handler.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Proof of concept illustrating the possibility of key
// handlers that process multi-key sequences.

def cons : a * b -> (a -> b) -> (a -> b) = \p. \k. \a.
if (a == fst p) {snd p} {k a}
end

def nil : a -> cmd unit = \a. return () end

// The delay around the first argument is necessary to prevent
// infinite recursion
def handlerB : {key -> cmd unit} -> key -> cmd unit = \hA. \k.
cons (key "b", move) nil k;
installKeyHandler "" (force hA)
end

// Typing 'a' then 'b' in sequence will cause the robot to move.
def handlerA : key -> cmd unit =
cons (key "a", installKeyHandler "" (handlerB {handlerA})) nil
end
26 changes: 26 additions & 0 deletions example/pilotmode.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
def cons : a * b -> (a -> b) -> (a -> b) = \p. \k. \a.
if (a == fst p) {snd p} {k a}
end

def nil : a -> cmd unit = \a. return () end

// Suitable to use as e.g.
// installKeyHandler "(S-)←↓↑→ [Del] [g]rab [h]arvest [d]rill [s]can [b]locked [u]pload" pilot
def pilot : key -> cmd unit =
cons (key "Up", move) $
cons (key "Down", turn back) $
cons (key "Left", turn left) $
cons (key "Right", turn right) $
cons (key "S-Up", turn north) $
cons (key "S-Down", turn south) $
cons (key "S-Left", turn west) $
cons (key "S-Right", turn east) $
cons (key "Del", selfdestruct) $
cons (key "g", res <- grab; log res) $
cons (key "h", res <- harvest; log res) $
cons (key "d", res <- drill forward; case res (\_. return ()) log) $
cons (key "s", res <- scan forward; case res (\_. return ()) log) $
cons (key "b", b <- blocked; if b {log "blocked"} {log "not blocked"}) $
cons (key "u", upload base) $
nil
end
12 changes: 12 additions & 0 deletions src/Swarm/Doc/Gen.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import Swarm.Game.Scenario (Scenario, loadScenario, scenarioRobots)
import Swarm.Game.WorldGen (testWorld2Entites)
import Swarm.Language.Capability (Capability)
import Swarm.Language.Capability qualified as Capability
import Swarm.Language.Key (specialKeyNames)
import Swarm.Language.Pretty (prettyText)
import Swarm.Language.Syntax (Const (..))
import Swarm.Language.Syntax qualified as Syntax
Expand All @@ -78,6 +79,8 @@ data GenerateDocs where
RecipeGraph :: GenerateDocs
-- | Keyword lists for editors.
EditorKeywords :: Maybe EditorType -> GenerateDocs
-- | List of special key names recognized by 'key' command
SpecialKeyNames :: GenerateDocs
CheatSheet :: PageAddress -> Maybe SheetType -> GenerateDocs
-- | List command introductions by tutorial
TutorialCoverage :: GenerateDocs
Expand Down Expand Up @@ -114,6 +117,7 @@ generateDocs = \case
putStrLn $ replicate 40 '-'
generateEditorKeywords et
mapM_ editorGen listEnums
SpecialKeyNames -> generateSpecialKeyNames
CheatSheet address s -> case s of
Nothing -> error "Not implemented for all Wikis"
Just st -> case st of
Expand Down Expand Up @@ -193,6 +197,14 @@ operatorNames = T.intercalate "|" $ map (escape . constSyntax) operators
c -> T.singleton c
escape = T.concatMap (\c -> if c `elem` special then T.snoc "\\\\" c else slashNotComment c)

-- ----------------------------------------------------------------------------
-- GENERATE SPECIAL KEY NAMES
-- ----------------------------------------------------------------------------

generateSpecialKeyNames :: IO ()
generateSpecialKeyNames =
T.putStr . T.unlines . Set.toList $ specialKeyNames

-- ----------------------------------------------------------------------------
-- GENERATE TABLES: COMMANDS, ENTITIES AND CAPABILITIES TO MARKDOWN TABLE
-- ----------------------------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions src/Swarm/Game/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ module Swarm.Game.State (
replNextValueIndex,
replWorking,
replActiveType,
inputHandler,
messageQueue,
lastSeenMessageTime,
focusedRobotID,
Expand Down Expand Up @@ -400,6 +401,7 @@ data GameState = GameState
, _needsRedraw :: Bool
, _replStatus :: REPLStatus
, _replNextValueIndex :: Integer
, _inputHandler :: Maybe (Text, Value)
, _messageQueue :: Seq LogEntry
, _lastSeenMessageTime :: TickNumber
, _focusedRobotID :: RID
Expand Down Expand Up @@ -584,6 +586,9 @@ replStatus :: Lens' GameState REPLStatus
-- | The index of the next it{index} value
replNextValueIndex :: Lens' GameState Integer

-- | The currently installed input handler and hint text.
inputHandler :: Lens' GameState (Maybe (Text, Value))

-- | A queue of global messages.
--
-- Note that we put the newest entry to the right.
Expand Down Expand Up @@ -1001,6 +1006,7 @@ initGameState = do
, _needsRedraw = False
, _replStatus = REPLDone Nothing
, _replNextValueIndex = 0
, _inputHandler = Nothing
, _messageQueue = Empty
, _lastSeenMessageTime = -1
, _focusedRobotID = 0
Expand Down Expand Up @@ -1055,6 +1061,7 @@ scenarioToGameState scenario userSeed toRun g = do
False -> REPLDone Nothing
True -> REPLWorking (Typed Nothing PolyUnit mempty)
, _replNextValueIndex = 0
, _inputHandler = Nothing
, _messageQueue = Empty
, _focusedRobotID = baseID
, _ticks = 0
Expand Down
15 changes: 15 additions & 0 deletions src/Swarm/Game/Step.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ import Swarm.Game.Value
import Swarm.Game.World qualified as W
import Swarm.Language.Capability
import Swarm.Language.Context hiding (delete)
import Swarm.Language.Key (parseKeyComboFull)
import Swarm.Language.Parse (runParser)
import Swarm.Language.Pipeline
import Swarm.Language.Pipeline.QQ (tmQ)
import Swarm.Language.Pretty (BulletList (BulletList, bulletListItems), prettyText)
Expand Down Expand Up @@ -1715,6 +1717,16 @@ execConst c vs s k = do
Fail -> case vs of
[VText msg] -> return $ Up (User msg) s k
_ -> badConst
Key -> case vs of
[VText ktxt] -> case runParser parseKeyComboFull ktxt of
Right kc -> return $ Out (VKey kc) s k
Left _ -> return $ Up (CmdFailed Key (T.unwords ["Unknown key", quote ktxt]) Nothing) s k
_ -> badConst
InstallKeyHandler -> case vs of
[VText hint, handler] -> do
inputHandler .= Just (hint, handler)
return $ Out VUnit s k
_ -> badConst
Reprogram -> case vs of
[VRobot childRobotID, VDelay cmd e] -> do
r <- get
Expand Down Expand Up @@ -2539,6 +2551,9 @@ compareValues v1 = case v1 of
VRcd m1 -> \case
VRcd m2 -> mconcat <$> (zipWithM compareValues `on` M.elems) m1 m2
v2 -> incompatCmp v1 v2
VKey kc1 -> \case
VKey kc2 -> return (compare kc1 kc2)
v2 -> incompatCmp v1 v2
VClo {} -> incomparable v1
VCApp {} -> incomparable v1
VDef {} -> incomparable v1
Expand Down
4 changes: 4 additions & 0 deletions src/Swarm/Language/Capability.hs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ data Capability
CRecord
| -- | Debug capability.
CDebug
| -- | Capability to handle keyboard input.
CHandleinput
| -- | God-like capabilities. For e.g. commands intended only for
-- checking challenge mode win conditions, and not for use by
-- players.
Expand Down Expand Up @@ -232,6 +234,8 @@ constCaps = \case
Chirp -> Just CDetectdirection
Watch -> Just CWakeself
Heading -> Just COrient
Key -> Just CHandleinput
InstallKeyHandler -> Just CHandleinput
-- ----------------------------------------------------------------
-- Text operations
Format -> Just CText
Expand Down
Loading