/
Menu.hs
82 lines (69 loc) · 2.32 KB
/
Menu.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module Yi.Keymap.Menu (
Menu,
MenuItem,
MenuContext(..),
menu, action, action_,
startMenu
) where
import Prelude ()
import Yi.Core
import Yi.File
import Yi.MiniBuffer (spawnMinibufferE)
import Control.Monad (fmap, void)
import Data.List (map, intercalate)
import Data.Char (isUpper, toLower)
import Data.Maybe (mapMaybe)
-- | Menu
type Menu = [MenuItem]
-- | Menu utem
data MenuItem =
MenuAction String (MenuContext -> Char -> Keymap) |
SubMenu String Menu
-- | Menu action context
data MenuContext = MenuContext {
parentBuffer :: BufferRef }
-- | Sub menu
menu :: String -> Menu -> MenuItem
menu = SubMenu
-- | Action on item
action_ :: (YiAction a x, Show x) => String -> a -> MenuItem
action_ title act = action title (const act)
-- | Action on item with context
action :: (YiAction a x, Show x) => String -> (MenuContext -> a) -> MenuItem
action title act = MenuAction title act' where
act' ctx c = char c ?>>! (do
withEditor closeBufferAndWindowE
runAction $ makeAction (act ctx))
-- | Fold menu item
foldItem
:: (String -> (MenuContext -> Char -> Keymap) -> a)
-> (String -> [a] -> a)
-> MenuItem
-> a
foldItem mA sM (MenuAction title act) = mA title act
foldItem mA sM (SubMenu title sm) = sM title (map (foldItem mA sM) sm)
-- | Fold menu
foldMenu
:: (String -> (MenuContext -> Char -> Keymap) -> a)
-> (String -> [a] -> a)
-> Menu
-> [a]
foldMenu mA sM = map (foldItem mA sM)
-- | Menu title to keymap
menuEvent :: String -> Maybe Char
menuEvent = fmap toLower . find isUpper
-- | Start menu action
startMenu :: Menu -> EditorM ()
startMenu m = do
ctx <- fmap MenuContext (gets currentBuffer)
startMenu' ctx m
where
startMenu' ctx = showMenu . foldMenu onItem onSub where
showMenu :: [(String, Maybe Keymap)] -> EditorM ()
showMenu is = void $ spawnMinibufferE menuItems (const (subMap is)) where
menuItems = (intercalate " " (map fst is))
onItem title act = (title, fmap (act ctx) (menuEvent title)) where
onSub title is = (title, fmap subMenu (menuEvent title)) where
subMenu c = char c ?>>! closeBufferAndWindowE >> showMenu is
subMap is = choice $ closeMenu : mapMaybe snd is where
closeMenu = spec KEsc ?>>! closeBufferAndWindowE