From 394afacc32fa95e177b3e4daf9334fc81092f4cb Mon Sep 17 00:00:00 2001
From: Daniel Firth <dan.firth@homotopic.tech>
Date: Wed, 18 Jan 2023 11:54:29 +0000
Subject: [PATCH] WIP: VIM

---
 horizon.dhall     |   2 +-
 shell/ShellRC.hs  | 105 +++++++++++++++++++++++++++++++++++++++-------
 shell/default.nix |   2 +
 3 files changed, 92 insertions(+), 17 deletions(-)

diff --git a/horizon.dhall b/horizon.dhall
index c4c0061c..6a37b3e1 100644
--- a/horizon.dhall
+++ b/horizon.dhall
@@ -1238,7 +1238,7 @@ let packages =
       , zlib = H.callHackage "zlib" "0.6.3.0"
       }
 
-in  H.HorizonExport.MakePackageSet
+in H.HorizonExport.MakePackageSet 
       { packagesDir = "pkgs"
       , packageSetFile = "initial-packages.nix"
       , packageSet = { compiler = "ghc-9.4.4", packages = toMap packages }
diff --git a/shell/ShellRC.hs b/shell/ShellRC.hs
index 25840b3a..03116e8d 100644
--- a/shell/ShellRC.hs
+++ b/shell/ShellRC.hs
@@ -1,17 +1,24 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedLists           #-}
 {-# LANGUAGE OverloadedStrings         #-}
 {-# LANGUAGE ViewPatterns              #-}
 {-# OPTIONS_GHC -Wno-missing-signatures #-}
 {-# OPTIONS_GHC -Wno-unused-imports #-}
+{-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}
 
 module ShellRC where
 
-import           Brick                     (BrickEvent (VtyEvent), EventM,
+import Polysemy.State
+import Control.Monad (void)
+import Control.Monad.IO.Class
+import           Brick                     (BrickEvent (VtyEvent), EventM, gets,
                                             Padding (..),
                                             ViewportType (Vertical), Widget,
                                             attrMap, attrName, bg, fg, hBox,
-                                            halt, on, padLeft, txt, vScrollBy,
+                                            halt, on, padLeftRight, txt, vScrollBy,
                                             viewport, viewportScroll, visible,
                                             withAttr)
 import qualified Brick
@@ -46,6 +53,7 @@ import           Network.HTTP.Simple
 import           Path
 import           Procex.Prelude
 import           Procex.Shell              hiding (promptFunction)
+import Polysemy
 import           System.Directory
 import           System.Environment
 
@@ -91,10 +99,10 @@ renderVersion :: Version -> Widget n
 renderVersion (MkVersion x) = txt x
 
 renderGitSource :: GitSource -> Widget n
-renderGitSource (MkGitSource u r s) = hBox (fmap (padLeft (Pad 1)) [txt "Git", renderRepo u, renderRevision r])
+renderGitSource (MkGitSource u r s) = hBox (fmap (padLeftRight 1) [txt "Git", renderRepo u, renderRevision r])
 
 renderHackageSource :: HackageSource -> Widget n
-renderHackageSource (MkHackageSource n v) = hBox (fmap (padLeft (Pad 1)) [txt "Hackage", renderName n, renderVersion v])
+renderHackageSource (MkHackageSource n v) = hBox (fmap (padLeftRight 1) [txt "Hackage", renderName n, renderVersion v])
 
 renderHaskellSource :: HaskellSource -> Widget n
 renderHaskellSource (FromGit x)     = renderGitSource x
@@ -116,15 +124,80 @@ packageListToTable = table . packageListToMatrix
 renderPackageList :: PackageListCursor -> Widget Text
 renderPackageList = viewport "Viewy" Vertical . renderTable . packageListToTable
 
-handleEvent :: BrickEvent Text e -> EventM Text PackageListCursor ()
-handleEvent (VtyEvent (EvKey KDown [])) = do
-  vScrollBy (viewportScroll "Viewy") 2
-  Brick.modify (\s -> fromMaybe s $ nonEmptyCursorSelectNext id id s)
-handleEvent (VtyEvent (EvKey KUp [])) = do
-  vScrollBy (viewportScroll "Viewy") (-2)
-  Brick.modify (\s -> fromMaybe s $ nonEmptyCursorSelectPrev id id s)
-handleEvent (VtyEvent (EvKey (KChar 'q') [])) = do
-  halt
+scrollDown :: EventM e (PackageListCursor, c) ()
+scrollDown =  Brick.modify (\(s, c) -> (fromMaybe s $ nonEmptyCursorSelectNext id id s, c))
+
+scrollUp :: EventM e (PackageListCursor, c) ()
+scrollUp =  Brick.modify (\(s, c) -> (fromMaybe s $ nonEmptyCursorSelectPrev id id s, c))
+
+type Vim :: Type -> (Type -> Type) -> Type -> Type
+data Vim y m a where
+  Del :: Vim y m ()
+  Find :: Vim y m ()
+  MoveDown :: Vim y m ()
+  MoveEndOfFile :: Vim y m ()
+  MoveLeft :: Vim y m ()
+  MoveRight :: Vim y m ()
+  MoveStartOfFile :: Vim y m ()
+  MoveUp :: Vim y m ()
+  Paste :: Vim y m ()
+  Quit :: Vim y m ()
+  Write :: Vim y m ()
+  Yank :: Vim y m ()
+
+makeSem ''Vim
+
+interpretVim :: Member (Embed (EventM e (PackageListCursor, c))) r => Sem (Vim y ': r) a -> Sem r a
+interpretVim = interpret $ \case
+  Del -> embed $ pure ()
+  Find -> embed $ pure ()
+  MoveDown -> embed $ scrollDown
+  MoveEndOfFile -> embed $ Brick.modify (\(x, c) -> (nonEmptyCursorSelectLast id id x, c))
+  MoveLeft -> embed $ pure ()
+  MoveRight -> embed $ pure ()
+  MoveStartOfFile -> embed $ Brick.modify (\(x, c) -> (nonEmptyCursorSelectFirst id id x , c))
+  MoveUp -> embed $ scrollUp
+  Paste -> embed $ pure ()
+  Quit -> embed $ halt
+  Yank -> embed $ pure ()
+
+brickEventToVim :: Members '[Vim y, State (Last Char)] r => BrickEvent Text e -> Sem r ()
+brickEventToVim (VtyEvent (EvKey KDown [])) = clear >> moveDown
+brickEventToVim (VtyEvent (EvKey KUp [])) = moveUp
+brickEventToVim (VtyEvent (EvKey (KChar 'j') [])) = moveDown
+brickEventToVim (VtyEvent (EvKey (KChar 'k') [])) = moveUp
+brickEventToVim (VtyEvent (EvKey (KChar 'G') [])) = moveEndOfFile
+brickEventToVim (VtyEvent (EvKey (KChar 'g') [])) = do
+  x <- get
+  case x of
+    Just 'g' -> do 
+       moveStartOfFile 
+       put Nothing
+    _ -> put $ Just 'g'
+brickEventToVim (VtyEvent (EvKey (KChar 'q') [])) = quit
+brickEventToVim (VtyEvent (EvKey (KChar 'w') [])) = write
+brickEventToVim _ = pure ()
+
+ 
+semStateToBrickState :: Member (Embed (EventM e s)) r => L.Lens' s t -> Sem (State t ': r) a -> Sem r a
+semStateToBrickState f = interpret $ \case
+  Put x -> embed $ Brick.put . L.set f x =<< Brick.get
+  Get   -> embed $ L.view f <$> Brick.get
+
+
+handleEvent :: BrickEvent Text e -> EventM Text (PackageListCursor, Maybe Char) ()
+handleEvent x = do
+  runM . semStateToBrickState (L.lens snd (\z k -> (fst z, k))) . interpretVim . brickEventToVim $ x
+handleEvent (VtyEvent (EvKey (KChar 'b') [])) = do
+  (MkName x, _) <- Brick.gets (nonEmptyCursorCurrent . fst)
+  let z = mq
+           "nix"
+            "build"
+            "-L"
+            (T.unpack $ ".#" <> x)
+            (pipeHOut 1 $ \_ stdout -> B.hGetContents stdout >>= B.putStr)
+            (pipeHOut 2 $ \_ stderr -> B.hGetContents stderr >>= B.writeFile "./log")
+  pure ()
 handleEvent _ = pure ()
 
 
@@ -133,12 +206,12 @@ appAttrMap = attrMap defAttr [ (attrName "highlight", fg yellow)
                              , (attrName "good", white `on` green)
                              ]
 
-packageListMain :: Brick.App PackageListCursor e Text
-packageListMain = Brick.App (pure . renderPackageList) (const $ const Nothing) handleEvent (pure ()) (const (appAttrMap))
+packageListMain :: Brick.App (PackageListCursor, Maybe Char) e Text
+packageListMain = Brick.App (pure . renderPackageList . fst) (const $ const Nothing) handleEvent (pure ()) (const (appAttrMap))
 
 go :: IO ()
 go = do
   x <- Dhall.inputFile @HorizonExport Dhall.auto "horizon.dhall"
   case x of
-    MakePackageSet (MkPackageSetExportSettings _ _ (MkPackageSet _ (MkPackageList (Map.toList -> y:ys)))) -> Brick.defaultMain packageListMain $ makeNonEmptyCursor id (y :| ys)
+    MakePackageSet (MkPackageSetExportSettings _ _ (MkPackageSet _ (MkPackageList (Map.toList -> y:ys)))) -> Brick.defaultMain packageListMain $ (makeNonEmptyCursor id (y :| ys), Nothing)
   pure ()
diff --git a/shell/default.nix b/shell/default.nix
index 4d1ced9f..184d5106 100644
--- a/shell/default.nix
+++ b/shell/default.nix
@@ -20,6 +20,8 @@ let
     lens
     lens-aeson
     path
+    polysemy-plugin
+    polysemy
     procex
     text
     vector
-- 
GitLab