Skip to content

Commit a4efa5a

Browse files
authored
Merge pull request #23 from garyb/halogen-bump
Update for Halogen 1.0.0
2 parents 117a372 + 3349982 commit a4efa5a

File tree

5 files changed

+85
-99
lines changed

5 files changed

+85
-99
lines changed

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
],
2929
"dependencies": {
3030
"purescript-ace": "^3.0.0",
31-
"purescript-halogen": "^0.12.0",
31+
"purescript-halogen": "^1.0.0-rc.2",
3232
"purescript-now": "^2.0.0",
3333
"purescript-random": "^2.0.0",
3434
"purescript-refs": "^2.0.0"

example/package.json

-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
"clean": "rimraf output && rimraf .pulp-cache",
55
"build": "pulp browserify --optimise --to example.js"
66
},
7-
"dependencies": {
8-
"virtual-dom": "^2.1.1"
9-
},
107
"devDependencies": {
118
"pulp": "^9.0.1",
129
"purescript": "^0.10.1",

example/src/Main.purs

+29-26
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@ import Control.Monad.Aff (Aff)
66
import Control.Monad.Eff (Eff)
77
import Control.Monad.Eff.Class (liftEff)
88
import Control.Monad.Eff.Random (RANDOM)
9-
import Control.Monad.Eff.Ref (REF)
109
import Control.Monad.Eff.Now (NOW)
1110

12-
import Data.Functor.Coproduct (Coproduct)
13-
import Data.Maybe (Maybe (..), fromMaybe)
11+
import Data.Maybe (Maybe(..))
1412

1513
import Halogen as H
16-
import Halogen.HTML.Indexed as HH
17-
import Halogen.Util (runHalogenAff, awaitBody)
14+
import Halogen.Aff as HA
15+
import Halogen.HTML as HH
16+
import Halogen.HTML.Events as HE
17+
import Halogen.VDom.Driver (runUI)
1818

1919
import Ace.Editor as Editor
2020
import Ace.EditSession as Session
21-
import Ace.Halogen.Component (AceState, AceQuery (TextChanged, GetText), aceConstructor)
21+
import Ace.Halogen.Component (AceQuery, AceMessage(..), aceComponent)
2222
import Ace.Types (ACE, Editor)
2323

2424
data Query a
25-
= UpdateText a
25+
= HandleMessage AceMessage a
2626

2727
type State =
2828
{ text String
@@ -35,24 +35,32 @@ initialState =
3535

3636
type AceSlot = Unit
3737

38-
type StateP g = H.ParentState State AceState Query AceQuery g AceSlot
39-
type QueryP = Coproduct Query (H.ChildF AceSlot AceQuery)
40-
type MainHtml g = H.ParentHTML AceState Query AceQuery g AceSlot
41-
type MainEffects = H.HalogenEffects (random RANDOM, now NOW, ref REF, ace ACE)
38+
type MainEffects = HA.HalogenEffects (random RANDOM, now NOW, ace ACE)
4239
type MainAff = Aff MainEffects
43-
type MainDSL = H.ParentDSL State AceState Query AceQuery MainAff AceSlot
4440

45-
ui H.Component (StateP MainAff) QueryP MainAff
46-
ui = H.parentComponent { render, eval, peek: Just (peek <<< H.runChildF) }
41+
type MainHtml = H.ParentHTML Query AceQuery AceSlot MainAff
42+
type MainDSL = H.ParentDSL State Query AceQuery AceSlot Void MainAff
43+
44+
ui H.Component HH.HTML Query Unit Void MainAff
45+
ui =
46+
H.parentComponent
47+
{ initialState: const initialState
48+
, render
49+
, eval
50+
, receiver: const Nothing
51+
}
4752
where
4853

49-
render State MainHtml MainAff
54+
render State MainHtml
5055
render state =
5156
HH.div_
52-
[ HH.Slot $ aceConstructor unit (initEditor state) Nothing
57+
[ HH.slot unit (component state) unit (HE.input HandleMessage)
5358
, HH.div_ [ HH.text state.text ]
5459
]
5560

61+
component :: State H.Component HH.HTML AceQuery Unit AceMessage MainAff
62+
component state = aceComponent (initEditor state) Nothing
63+
5664
initEditor State Editor MainAff Unit
5765
initEditor state editor = liftEff $ do
5866
session ← Editor.getSession editor
@@ -61,15 +69,10 @@ ui = H.parentComponent { render, eval, peek: Just (peek <<< H.runChildF) }
6169
pure unit
6270

6371
eval Query ~> MainDSL
64-
eval (UpdateText next) =
65-
pure next
66-
67-
peek forall x. AceQuery x MainDSL Unit
68-
peek (TextChanged _) = do
69-
text ← H.query unit $ H.request GetText
70-
H.modify (_ { text = fromMaybe "" text })
71-
peek _ =
72-
pure unit
72+
eval = case _ of
73+
HandleMessage (TextChanged text) next → do
74+
H.modify (_ { text = text })
75+
pure next
7376

7477
main Eff MainEffects Unit
75-
main = runHalogenAff $ H.runUI ui (H.parentState initialState) =<< awaitBody
78+
main = HA.runHalogenAff (runUI ui unit =<< HA.awaitBody)

package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
"private": true,
33
"scripts": {
44
"clean": "rimraf output && rimraf .pulp-cache",
5-
"build": "jshint src && jscs src && pulp build --censor-lib --strict",
5+
"build": "jshint src && jscs src && pulp build -- --censor-lib --strict",
66
"example": "bower link && cd example && bower link purescript-ace-halogen && npm i --production && npm run -s build"
77
},
88
"devDependencies": {
99
"jscs": "^3.0.7",
1010
"jshint": "^2.9.4",
11-
"pulp": "^9.0.1",
12-
"purescript": "^0.10.1",
13-
"purescript-psa": "^0.3.9",
11+
"pulp": "^10.0.0",
12+
"purescript": "^0.10.5",
13+
"purescript-psa": "^0.4.0",
1414
"rimraf": "^2.5.4"
1515
}
1616
}

src/Ace/Halogen/Component.purs

+51-65
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
module Ace.Halogen.Component
22
( aceComponent
3-
, aceConstructor
43
, AceQuery(..)
5-
, AceState(..)
6-
, initialAceState
4+
, AceMessage(..)
75
, AceEffects
86
, Autocomplete(..)
97
, CompleteFn
@@ -13,14 +11,14 @@ import Prelude
1311

1412
import Control.Monad.Aff (Aff, runAff)
1513
import Control.Monad.Aff.AVar (AVAR)
16-
import Control.Monad.Aff.Free (class Affable)
1714
import Control.Monad.Eff (Eff)
15+
import Control.Monad.Aff.Class (class MonadAff)
1816
import Control.Monad.Eff.Now (NOW, now)
1917
import Control.Monad.Eff.Random (random, RANDOM)
2018
import Control.Monad.Eff.Ref (Ref, REF, readRef, writeRef, modifyRef)
2119

2220
import Data.DateTime.Instant (unInstant)
23-
import Data.Foldable (traverse_, for_)
21+
import Data.Foldable (traverse_)
2422
import Data.Maybe (Maybe(..), maybe)
2523
import Data.Newtype (unwrap)
2624
import Data.StrMap (StrMap)
@@ -37,8 +35,8 @@ import DOM (DOM)
3735
import DOM.HTML.Types (HTMLElement)
3836

3937
import Halogen as H
40-
import Halogen.HTML.Indexed as HH
41-
import Halogen.HTML.Properties.Indexed as HP
38+
import Halogen.HTML as HH
39+
import Halogen.HTML.Properties as HP
4240

4341
-- | Effectful knot of autocomplete functions. It's needed because
4442
-- | `languageTools.addCompleter` is global and adds completer to
@@ -129,19 +127,19 @@ type AceEffects eff =
129127
-- | - `Just Live` - enables live autocomplete
130128
-- | - `SetCompleteFn` - sets function providing autocomplete variants.
131129
-- | - `GetEditor` - returns ace editor instance handled by this component.
132-
-- | - `TextChanged` - raised internally when the value in the editor is
133-
-- | changed. Allows for parent component to observe when the value changes
134-
-- | via the `peek` mechanism.
135130
data AceQuery a
136-
= SetElement (Maybe HTMLElement) a
137-
| Init a
131+
= Init a
138132
| Quit a
139133
| GetText (String a)
140134
| SetText String a
141135
| SetAutocomplete (Maybe Autocomplete) a
142136
| SetCompleteFn ( eff. CompleteFn eff) a
143137
| GetEditor (Maybe Editor a)
144-
| TextChanged a
138+
| HandleChange (H.SubscribeStatus -> a)
139+
140+
-- | Ace output messages
141+
-- | - `AceValueChanged` - raised when the value in the editor is changed.
142+
data AceMessage = TextChanged String
145143

146144
-- | The type for autocomplete function s. Takes editor, session, text position,
147145
-- | prefix, and returns array of possible completions in the `Aff` monad.
@@ -158,108 +156,96 @@ type CompleteFn eff
158156
type AceState =
159157
{ key Maybe String
160158
, editor Maybe Editor
161-
, element Maybe HTMLElement
162159
}
163160

161+
type DSL m = H.ComponentDSL AceState AceQuery AceMessage m
162+
164163
-- | An initial empty state value.
165-
initialAceState AceState
166-
initialAceState =
164+
initialState AceState
165+
initialState =
167166
{ key: Nothing
168167
, editor: Nothing
169-
, element: Nothing
170168
}
171169

172170
-- | The Ace component.
173171
aceComponent
174-
eff g
175-
. (Monad g, Affable (AceEffects eff) g)
176-
(Editor g Unit)
172+
eff m
173+
. MonadAff (AceEffects eff) m
174+
(Editor m Unit)
177175
Maybe Autocomplete
178-
H.Component AceState AceQuery g
179-
aceComponent setup resume = H.lifecycleComponent
180-
{ render
176+
H.Component HH.HTML AceQuery Unit AceMessage m
177+
aceComponent setup resume =
178+
H.lifecycleComponent
179+
{ initialState: const initialState
180+
, render
181181
, eval: eval setup resume
182182
, initializer: Just (H.action Init)
183183
, finalizer: Just (H.action Quit)
184+
, receiver: const Nothing
184185
}
185186

186187
render AceState H.ComponentHTML AceQuery
187-
render = const $ HH.div [ HP.ref (H.action <<< SetElement) ] []
188+
render = const $ HH.div [ HP.ref (H.RefLabel "container") ] []
188189

189-
eval eff g
190-
. (Monad g, Affable (AceEffects eff) g)
191-
(Editor g Unit)
190+
eval eff m
191+
. MonadAff (AceEffects eff) m
192+
(Editor m Unit)
192193
Maybe Autocomplete
193194
AceQuery
194-
~> H.ComponentDSL AceState AceQuery g
195+
~> DSL m
195196
eval setup resume = case _ of
196-
SetElement el next → do
197-
state ← H.get
198-
for_ state.editor $ H.fromEff <<< Editor.destroy
199-
H.modify _{ element = el, editor = Nothing }
200-
pure next
201197

202198
Init next → do
203-
el ← H.gets _.element
204-
for_ el \el' → do
205-
key ← H.gets _.key >>= maybe (H.fromEff genKey) pure
206-
editor ← H.fromEff $ Ace.editNode el' Ace.ace
207-
H.set { key: Just key, editor: Just editor, element: Just el' }
208-
H.fromEff do
199+
H.getHTMLElementRef (H.RefLabel "container") >>= traverse_ \el → do
200+
key ← H.gets _.key >>= maybe (H.liftEff genKey) pure
201+
editor ← H.liftEff $ Ace.editNode el Ace.ace
202+
H.put { key: Just key, editor: Just editor }
203+
H.liftEff do
209204
enableAutocomplete
210205
setAutocompleteResume resume editor
211206
Editor.onFocus editor $ writeRef focused key
212-
session ← H.fromEff $ Editor.getSession editor
213-
H.subscribe $ H.eventSource_ (Session.onChange session) do
214-
pure $ H.action TextChanged
215-
H.liftH $ setup editor
207+
session ← H.liftEff $ Editor.getSession editor
208+
H.subscribe $ H.eventSource_ (Session.onChange session) (H.request HandleChange)
209+
H.lift $ setup editor
216210
pure next
217211

218212
Quit next → do
219213
H.gets _.key
220214
>>= traverse_ \key →
221-
H.fromEff $ modifyRef completeFns $ Sm.delete key
215+
H.liftEff $ modifyRef completeFns $ Sm.delete key
222216
pure next
223217

224218
GetEditor k →
225219
map k $ H.gets _.editor
226220

227221
GetText k →
228-
H.gets _.editor
229-
>>= maybe (pure "") (H.fromEff <<< Editor.getValue)
230-
>>= k >>> pure
222+
pure <<< k =<< getText
231223

232224
SetText text next → do
233225
H.gets _.editor
234226
>>= traverse_ \editor → do
235-
current ← H.fromEff $ Editor.getValue editor
227+
current ← H.liftEff $ Editor.getValue editor
236228
when (text /= current) $ void
237-
$ H.fromEff (Editor.setValue text Nothing editor)
229+
$ H.liftEff (Editor.setValue text Nothing editor)
238230
pure next
239231

240232
SetAutocomplete mbAc next → do
241233
H.gets _.editor
242-
>>= traverse_ (H.fromEff <<< setAutocompleteResume mbAc)
234+
>>= traverse_ (H.liftEff <<< setAutocompleteResume mbAc)
243235
pure next
244236

245237
SetCompleteFn fn next → do
246238
H.gets _.key
247239
>>= traverse_ \key →
248-
H.fromEff $ modifyRef completeFns $ Sm.insert key fn
240+
H.liftEff $ modifyRef completeFns $ Sm.insert key fn
249241
pure next
250242

251-
TextChanged next → pure next
243+
HandleChange k → do
244+
H.raise <<< TextChanged =<< getText
245+
pure $ k H.Listening
252246

253-
-- | A convenience function for creating a `SlotConstructor` for an Ace
254-
-- | component.
255-
aceConstructor
256-
p eff
257-
. p
258-
(Editor Aff (AceEffects eff) Unit)
259-
Maybe Autocomplete
260-
H.SlotConstructor AceState AceQuery (Aff (AceEffects eff)) p
261-
aceConstructor p setup mbAc =
262-
H.SlotConstructor p \_ →
263-
{ component: aceComponent setup mbAc
264-
, initialState: initialAceState
265-
}
247+
where
248+
249+
getText :: DSL m String
250+
getText =
251+
maybe (pure "") (H.liftEff <<< Editor.getValue) =<< H.gets _.editor

0 commit comments

Comments
 (0)