11module 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
1412import Control.Monad.Aff (Aff , runAff )
1513import Control.Monad.Aff.AVar (AVAR )
16- import Control.Monad.Aff.Free (class Affable )
1714import Control.Monad.Eff (Eff )
15+ import Control.Monad.Aff.Class (class MonadAff )
1816import Control.Monad.Eff.Now (NOW , now )
1917import Control.Monad.Eff.Random (random , RANDOM )
2018import Control.Monad.Eff.Ref (Ref , REF , readRef , writeRef , modifyRef )
2119
2220import Data.DateTime.Instant (unInstant )
23- import Data.Foldable (traverse_ , for_ )
21+ import Data.Foldable (traverse_ )
2422import Data.Maybe (Maybe (..), maybe )
2523import Data.Newtype (unwrap )
2624import Data.StrMap (StrMap )
@@ -37,8 +35,8 @@ import DOM (DOM)
3735import DOM.HTML.Types (HTMLElement )
3836
3937import 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.
135130data 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
158156type 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.
173171aceComponent
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
186187render ∷ 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
195196eval 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