Skip to content

Commit eeca57f

Browse files
committed
Update template for example plugin
1 parent b0c01b7 commit eeca57f

File tree

1 file changed

+42
-41
lines changed

1 file changed

+42
-41
lines changed

stack-template.hsfiles

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ executable my-nvim-hs
2222
, Neovim.Example.Plugin.Fibonacci
2323
, Neovim.Example.Plugin.Random
2424
build-depends: base >= 4.7 && < 5
25-
, nvim-hs >= 0.2.5 && < 1.0.0
26-
-- The dependency below is only needed for the example plugin
25+
, nvim-hs >= 1 && < 2
26+
-- The dependencies below are only needed for the example plugin
2727
, random
28+
, unliftio
2829
default-language: Haskell2010
2930

3031
{-# START_FILE lib/Neovim/Example/Plugin.hs #-}
@@ -40,29 +41,24 @@ import Neovim
4041
import Neovim.Example.Plugin.Random (nextRandom, setNextRandom, randomNumbers)
4142
import Neovim.Example.Plugin.Fibonacci (fibonacci)
4243

43-
plugin :: Neovim (StartupConfig NeovimConfig) () NeovimPlugin
44+
plugin :: Neovim (StartupConfig NeovimConfig) NeovimPlugin
4445
plugin = do
4546
randomPluginState <- randomNumbers
4647
wrapPlugin Plugin
47-
{ exports =
48+
{ environment = randomPluginState
49+
, exports =
4850
[ $(function' 'fibonacci) Sync
4951
-- Notice the quotation mark before the functin name, this is
5052
-- important!
51-
]
52-
, statefulExports =
53-
[ StatefulFunctionality
54-
{ readOnly = ()
55-
, writable = randomPluginState
56-
, functionalities =
57-
[ $(function' 'nextRandom) Sync
58-
, $(function "SetNextRandom" 'setNextRandom) Async
59-
]
60-
}
53+
54+
, $(function' 'nextRandom) Sync
55+
, $(function "SetNextRandom" 'setNextRandom) Async
6156
]
6257
}
6358

6459
{-# START_FILE lib/Neovim/Example/Plugin/Random.hs #-}
6560
{-# LANGUAGE TemplateHaskell #-}
61+
{-# LANGUAGE TemplateHaskell #-}
6662
module Neovim.Example.Plugin.Random
6763
( nextRandom
6864
, setNextRandom
@@ -71,45 +67,50 @@ module Neovim.Example.Plugin.Random
7167

7268
import Neovim
7369
import System.Random (newStdGen, randoms)
70+
import UnliftIO.STM (TVar, atomically, readTVar, modifyTVar, newTVarIO)
7471

75-
-- | This is the start up code. It initializes the random number generator and
76-
-- returns a convenient list of random numbers.
77-
--
78-
-- Except for the last @[Int16]@ return values, this type signature is mandatory
79-
-- for your startup code. The internals of the plugin recompilation leak here a
80-
-- bit, it might be changed in the future. If you don't mind warnings, you can
81-
-- leave the signature undefined, but then you would have to add a type
82-
-- signature to the value of @randoms g@.
72+
-- | This type alias encodes the type of your plugin's environment, namely
73+
-- '(TVar [Int16)' in this case.
8374
--
84-
-- See <https://github.com/neovimhaskell/nvim-hs/issues/13> for details.
75+
-- Since this plugin needs to store some state, we have to put it in a mutable
76+
-- variable. I chose TVar here because I like the Software Transactional Memory
77+
-- library.
78+
type MyNeovim a = Neovim (TVar [Int16]) a
79+
80+
-- | This is the start up code. It initializes the random number generator and
81+
-- returns a convenient list of random numbers. It returns the environment and
82+
-- is executed in the startup code, so this is the only place where you can't
83+
-- use the type alias defined above.
8584
--
8685
-- Neovim isn't so good with big numbers, so limit to 16 bits.
87-
randomNumbers :: Neovim (StartupConfig NeovimConfig) () [Int16]
86+
randomNumbers :: Neovim startupEnv (TVar [Int16])
8887
randomNumbers = do
8988
g <- liftIO newStdGen -- Create a new seed for a pseudo random number generator
90-
return (randoms g) -- Return an infinite list of random numbers
91-
92-
-- You could write this shorter in more idiomatic Haskell:
93-
-- randomNumbers = randoms <$> liftIO newStdGen
89+
newTVarIO (randoms g) -- Put an infinite list of random numbers into a TVar
9490

9591
-- | Get the next random number and update the state of the list.
96-
nextRandom :: Neovim r [Int16] Int16
92+
nextRandom :: MyNeovim Int16
9793
nextRandom = do
98-
r <- gets head -- get the head of the infinite random number list
99-
modify tail -- set the list to its tail
100-
return r
94+
tVarWithRandomNumbers <- ask
95+
atomically $ do
96+
-- pick the head of our list of random numbers
97+
r <- head <$> readTVar tVarWithRandomNumbers
98+
99+
-- Since we do not want to return the same number all over the place
100+
-- remove the head of our list of random numbers
101+
modifyTVar tVarWithRandomNumbers tail
102+
103+
return r
101104

102-
-- An alternative equivalent implementation with pattern matching on the list
103-
-- nextRandom :: Neovim r [Int16] Int16
104-
-- nextRandom = do
105-
-- (r:rs) <- get
106-
-- put rs
107-
-- return r
108105

109106
-- | You probably don't want this in a random number generator, but this shows
110107
-- hoy you can edit the state of a stateful plugin.
111-
setNextRandom :: Int16 -> Neovim r [Int16] ()
112-
setNextRandom n = modify (n:) -- cons n to the front of the infinite list
108+
setNextRandom :: Int16 -> MyNeovim ()
109+
setNextRandom n = do
110+
tVarWithRandomNumbers <- ask
111+
112+
-- cons n to the front of the infinite list
113+
atomically $ modifyTVar tVarWithRandomNumbers (n:)
113114

114115
{-# START_FILE lib/Neovim/Example/Plugin/Fibonacci.hs #-}
115116
module Neovim.Example.Plugin.Fibonacci
@@ -124,7 +125,7 @@ fibonacciNumbers = 0:fibs -- Since were using !! to index an element in a list,
124125
where fibs = 1:scanl1 (+) fibs
125126

126127
-- | Neovim is not really good with big numbers, so we return a 'String' here.
127-
fibonacci :: Int -> Neovim' String
128+
fibonacci :: Int -> Neovim env String
128129
fibonacci n = return . show $ fibonacciNumbers !! n
129130

130131
{-# START_FILE nvim.hs #-}

0 commit comments

Comments
 (0)