intricacy-0.9.0.0: KeyBindings.hs
-- This file is part of Intricacy
-- Copyright (C) 2013-2025 Martin Bays <mbays@sdf.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of version 3 of the GNU General Public License as
-- published by the Free Software Foundation, or any later version.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see http://www.gnu.org/licenses/.
{-# LANGUAGE CPP #-}
module KeyBindings (KeyBindings, bindings, findBindings, findBinding, showKey,
showKeyChar, showKeyFriendly, showKeyFriendlyShort) where
import Data.Bits (xor)
import Data.Char
import Data.List
import Command
import GameStateTypes
import Hex
import InputMode
type KeyBindings = [ (Char,Command) ]
ctrl, unctrl, meta, unmeta :: Char -> Char
ctrl = toEnum . xor 64 . fromEnum
meta = toEnum . xor 128 . fromEnum
unctrl = ctrl
unmeta = meta
lowerToo :: KeyBindings -> KeyBindings
lowerToo = concatMap addLower
where addLower b@(c, cmd) = [ b, (toLower c, cmd) ]
qwertyWASDish =
[ ('e', CmdDir WHSSelected hu)
, ('a', CmdDir WHSSelected $ neg hu)
, ('s', CmdDir WHSSelected hw)
, ('w', CmdDir WHSSelected $ neg hw)
, ('q', CmdDir WHSSelected hv)
, ('d', CmdDir WHSSelected $ neg hv)
, ('c', CmdRotate WHSSelected 1)
, ('z', CmdRotate WHSSelected $ -1)
]
keypadHex =
[ ('5', CmdWait)
, ('6', CmdDir WHSSelected hu)
, ('4', CmdDir WHSSelected $ neg hu)
, ('1', CmdDir WHSSelected hw)
, ('9', CmdDir WHSSelected $ neg hw)
, ('7', CmdDir WHSSelected hv)
, ('3', CmdDir WHSSelected $ neg hv)
, ('8', CmdRotate WHSSelected 1)
, ('2', CmdRotate WHSSelected $ -1)
]
selectedMovement = qwertyWASDish ++ keypadHex
qwertyViHex =
[ ('l', CmdDir WHSHook hu)
, ('h', CmdDir WHSHook $ neg hu)
, ('b', CmdDir WHSHook hw)
, ('u', CmdDir WHSHook $ neg hw)
, ('y', CmdDir WHSHook hv)
, ('n', CmdDir WHSHook $ neg hv)
, ('L', CmdDir WHSWrench hu)
, ('H', CmdDir WHSWrench $ neg hu)
, ('B', CmdDir WHSWrench hw)
, ('U', CmdDir WHSWrench $ neg hw)
, ('Y', CmdDir WHSWrench hv)
, ('N', CmdDir WHSWrench $ neg hv)
, ('k', CmdRotate WHSHook 1)
, ('j', CmdRotate WHSHook $ -1)
]
{-
qwertyLeftHex =
[ ('d', CmdDir WHSHook hu)
, ('a', CmdDir WHSHook $ neg hu)
, ('z', CmdDir WHSHook hw)
, ('e', CmdDir WHSHook $ neg hw)
, ('w', CmdDir WHSHook hv)
, ('x', CmdDir WHSHook $ neg hv)
, ('D', CmdDir WHSWrench hu)
, ('A', CmdDir WHSWrench $ neg hu)
, ('Z', CmdDir WHSWrench hw)
, ('E', CmdDir WHSWrench $ neg hw)
, ('W', CmdDir WHSWrench hv)
, ('X', CmdDir WHSWrench $ neg hv)
, ('q', CmdRotate WHSHook 1)
, ('c', CmdRotate WHSHook $ -1)
, ('S', CmdWait)
, ('s', CmdWait)
]
dvorakMidHex =
[ ('i', CmdDir WHSWrench hu)
, ('e', CmdDir WHSWrench $ neg hu)
, ('j', CmdDir WHSWrench hw)
, ('y', CmdDir WHSWrench $ neg hw)
, ('p', CmdDir WHSWrench hv)
, ('k', CmdDir WHSWrench $ neg hv)
]
-}
miscLockGlobal = lowerToo
[ ('\b', CmdUndo)
, ('\r', CmdRedo)
, ('\n', CmdRedo)
, (ctrl 'R', CmdRedo)
, (ctrl 'Y', CmdRedo)
#ifndef CURSES
, (ctrl 'Z', CmdUndo)
#endif
, ('R', CmdReset)
, ('.', CmdWait)
, ('M', CmdMark)
, ('\'', CmdJumpMark)
] <>
[ ('X', CmdUndo)
]
miscGlobal =
[ ('\ESC', CmdQuit)
, ('Q', CmdQuit)
, (ctrl 'Q', CmdQuit)
, (ctrl 'C', CmdQuit)
, ('?', CmdHelp)
, (ctrl 'B', CmdBind Nothing)
, (ctrl 'L', CmdRedraw)
#ifdef CURSES
, (ctrl 'Z', CmdSuspend)
#endif
, ('%', CmdToggleColourMode)
]
playOnly = lowerToo
[ ('O', CmdOpen)
, (' ', CmdWait)
, ('x', CmdToggle)
, ('\t', CmdToggle)
, ('*', CmdTile $ WrenchTile zero)
, ('/', CmdTile HookTile)
, ('@', CmdTile HookTile)
]
replayOnly =
[ (' ', CmdReplayForward 1)
]
editMisc = lowerToo
[ ('P', CmdPlay)
, ('T', CmdTest)
] <>
[ ('W', CmdWriteState)
, (ctrl 'S', CmdWriteState)
, (' ', CmdSelect)
, ('=', CmdMerge)
, ('0', CmdDelete)
]
tilesPaintRow = lowerToo
[ ('H', CmdTile BallTile)
, ('B', CmdTile $ ArmTile zero False)
, ('G', CmdTile $ PivotTile zero)
, ('V', CmdTile $ SpringTile Relaxed zero)
, ('F', CmdTile $ BlockTile [])
, ('x', CmdDelete)
]
tilesAscii =
[ ('o', CmdTile $ PivotTile zero)
, ('O', CmdTile BallTile)
, ('S', CmdTile $ SpringTile Relaxed zero)
, ('$', CmdTile $ SpringTile Relaxed zero)
--, ('s', CmdTile $ SpringTile Stretched zero)
--, ('$', CmdTile $ SpringTile Compressed zero)
, ('-', CmdTile $ ArmTile zero False)
--, ('-', CmdTile $ ArmTile hu False)
, ('\\', CmdTile $ ArmTile hv False)
, ('/', CmdTile $ ArmTile hw False)
, ('@', CmdTile HookTile)
, ('*', CmdTile $ WrenchTile zero)
, ('#', CmdTile $ BlockTile [])
]
editOnly = tilesPaintRow ++ editMisc ++ tilesAscii
playBindings = playOnly ++ selectedMovement ++ qwertyViHex ++ miscGlobal ++ miscLockGlobal
replayBindings = replayOnly ++ miscGlobal ++ miscLockGlobal
editBindings = editOnly ++ selectedMovement ++ miscGlobal ++ miscLockGlobal
initBindings = lowerToo [ ('S', CmdSolveInit Nothing) ] ++ miscGlobal
metaBindings = lowerToo
[ ('C', CmdSelCodename Nothing)
, ('H', CmdHome)
, ('B', CmdBackCodename)
, ('S', CmdSolve Nothing)
, ('D', CmdDeclare Nothing)
, ('V', CmdViewSolution Nothing)
, ('R', CmdRegister)
, ('P', CmdPlaceLock Nothing)
, (ctrl 'R', CmdRetireLock)
, ('E', CmdEdit)
, ('L', CmdSelectLock)
, ('O', CmdPrevLock)
, ('N', CmdNextLock)
, ('A', CmdAuth)
, ('I', CmdInitiation)
, ('+', CmdShowRetired)
, ('#', CmdPlayLockSpec Nothing)
, ('$', CmdSetServer)
, ('^', CmdToggleCacheOnly)
, ('>', CmdNextPage)
, ('<', CmdPrevPage)
, (ctrl 'D', CmdDeleteLock)
] ++ miscGlobal
impatienceBindings = lowerToo
[ ('Q', CmdQuit)
, (ctrl 'C', CmdQuit) ]
bindings :: InputMode -> KeyBindings
bindings IMEdit = editBindings
bindings IMPlay = playBindings
bindings IMInit = initBindings
bindings IMMeta = metaBindings
bindings IMReplay = replayBindings
bindings IMImpatience = impatienceBindings
bindings _ = []
findBindings :: KeyBindings -> Command -> [Char]
findBindings bdgs cmd = nub
$ [ ch | (ch,cmd') <- bdgs, cmd'==cmd ]
++ [ ch | CmdInputChar ch <- [cmd] ]
findBinding :: KeyBindings -> Command -> Maybe Char
findBinding _ (CmdInputChar ch) = Just ch
findBinding bdgs cmd = find (\ch -> lookup ch bdgs == Just cmd) $ findBindings bdgs cmd
showKey :: Char -> String
showKey ch
| isAscii (unmeta ch) = 'M':'-':showKey (unmeta ch)
| isPrint ch = [ch]
| isPrint (unctrl ch) = '^':[unctrl ch]
| otherwise = "[?]"
showKeyFriendly ' ' = "space"
showKeyFriendly '\r' = "return"
showKeyFriendly '\n' = "newline"
showKeyFriendly '\t' = "tab"
showKeyFriendly '\b' = "backspace"
showKeyFriendly '\ESC' = "escape"
showKeyFriendly ch = showKey ch
showKeyFriendlyShort '\r' = "ret"
showKeyFriendlyShort '\t' = "tab"
showKeyFriendlyShort '\b' = "bsp"
showKeyFriendlyShort '\ESC' = "esc"
showKeyFriendlyShort ch = showKey ch
showKeyChar :: Char -> Char
showKeyChar ch
| isAscii (unmeta ch) = '['
| isPrint ch = ch
| isPrint (unctrl ch) = '^'
| otherwise = '?'