-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A modular text editor -- -- A modular text editor This is only a snippet, see the project's -- README. -- -- Rasa is a text editor project with a few interesting goals. For better -- or worse it attempts to be as modular as possible. This means that -- most functionality which would typically be considered to be -- core in other editors is implemented as extensions in Rasa. -- This approach comes with its own share of pros and cons, for instance: -- -- Pros -- -- -- -- Cons -- -- -- -- While highly experimental, I've found the current API to be quite -- expressive and adaptable; for instance I was able to implement the -- notion of multiple cursors using the extension API in less than a day. -- I hope to keep the learning curve low as development continues. -- -- Getting Started -- -- First clone the Github repo and try running the example-config -- included there. Once you get it running (see the README) then -- you can customize your keymap to add a few mappings you like. Then I'd -- check out the Building your own extensions guide. It goes in -- depth into everything you'd want to know! -- -- If you have any issues (and I'm sure there'll be a few; it's a new -- project!) please report them here and we'll talk about it! @package rasa @version 0.1.7 module Rasa.Internal.Text -- | An iso which converts to/from YiString -> Text asText :: Iso' YiString Text -- | An iso which converts to/from YiString -> String asString :: Iso' YiString String -- | An iso which converts to/from YiString -> [YiString] asLines :: Iso' YiString [YiString] module Rasa.Internal.Extensions -- | A wrapper around an extension of any type so it can be stored in an -- ExtMap data Ext Ext :: a -> Ext -- | A map of extension types to their current value. type ExtMap = Map TypeRep Ext instance GHC.Show.Show Rasa.Internal.Extensions.Ext module Rasa.Internal.Buffer -- | A buffer, holds the text in the buffer and any extension states that -- are set on the buffer. data Buffer -- | This allows creation of polymorphic lenses over any type which has -- access to a Buffer class HasBuffer a buffer :: HasBuffer a => Lens' a Buffer -- | This lens focuses the text of the in-scope buffer. text :: HasBuffer b => Lens' b YiString -- | bufExt is a lens which will focus a given extension's state -- within a buffer (within a BufAction). The lens will -- automagically focus the required extension by using type inference. -- It's a little bit of magic, if you treat the focus as a member of your -- extension state it should just work out. -- -- This lens falls back on the extension's Default instance (when -- getting) if nothing has yet been stored. bufExt :: forall a s. (Show a, Typeable a, Default a, HasBuffer s) => Lens' s a -- | A wrapper around an extension of any type so it can be stored in an -- ExtMap data Ext Ext :: a -> Ext -- | Creates a new buffer from the given text. mkBuffer :: YiString -> Buffer instance GHC.Show.Show Rasa.Internal.Buffer.Buffer instance Rasa.Internal.Buffer.HasBuffer Rasa.Internal.Buffer.Buffer module Rasa.Internal.Editor -- | This is the primary state of the editor. data Editor -- | This allows polymorphic lenses over anything that has access to an -- Editor context class HasEditor a editor :: HasEditor a => Lens' a Editor -- | A lens over the map of available buffers buffers :: HasEditor e => Lens' e (IntMap Buffer) -- | A lens over the exiting status of the editor exiting :: HasEditor e => Lens' e Bool -- | ext is a lens which will focus the extension state that matches -- the type inferred as the focal point. It's a little bit of magic, if -- you treat the focus as a member of your extension state it should just -- work out. -- -- This lens falls back on the extension's Default instance (when -- getting) if nothing has yet been stored. ext :: forall a e. (Show a, Typeable a, Default a, HasEditor e) => Lens' e a -- | bufExt is a lens which will focus a given extension's state -- within a buffer (within a BufAction). The lens will -- automagically focus the required extension by using type inference. -- It's a little bit of magic, if you treat the focus as a member of your -- extension state it should just work out. -- -- This lens falls back on the extension's Default instance (when -- getting) if nothing has yet been stored. bufExt :: forall a s. (Show a, Typeable a, Default a, HasBuffer s) => Lens' s a -- | A lens over the next buffer id to be allocated nextBufId :: HasEditor e => Lens' e Int -- | An opaque reference to a buffer (The contained Int is not meant to be -- altered). It is possible for references to become stale if buffers are -- deleted. Operations over invalid BufRef's are simply ignored and -- return Nothing if a value was expected. newtype BufRef BufRef :: Int -> BufRef instance GHC.Show.Show Rasa.Internal.Editor.Editor instance Rasa.Internal.Editor.HasEditor Rasa.Internal.Editor.Editor instance Data.Default.Class.Default Rasa.Internal.Editor.Editor instance GHC.Classes.Ord Rasa.Internal.Editor.BufRef instance GHC.Classes.Eq Rasa.Internal.Editor.BufRef instance GHC.Show.Show Rasa.Internal.Editor.BufRef module Rasa.Internal.Events -- | The Event type represents a common denominator for all actions that -- could occur Event transmitters express events that have occured as a -- member of this type. At the moment it's quite sparse, but it will -- expand as new types of events are needed. -- -- This event is dispatched exactly once when the editor starts up. data Init Init :: Init -- | This event is dispatched immediately before dispatching any events -- from asyncronous event listeners (like Keypresss) data BeforeEvent BeforeEvent :: BeforeEvent -- | This event is dispatched immediately before dispatching the -- OnRender event. data BeforeRender BeforeRender :: BeforeRender -- | This event is dispatched when it's time for extensions to render to -- screen. data OnRender OnRender :: OnRender -- | This event is dispatched immediately after dispatching -- OnRender. data AfterRender AfterRender :: AfterRender -- | This event is dispatched before exiting the editor, listen for this to -- do any clean-up (saving files, etc.) data Exit Exit :: Exit -- | This event is dispatched after adding a new buffer. The contained -- BufRef refers to the new buffer. data BufAdded BufAdded :: BufRef -> BufAdded -- | This event is dispatched in response to keyboard key presses. It -- contains both the char that was pressed and any modifiers (Mod) -- that where held when the key was pressed. data Keypress Keypress :: Char -> [Mod] -> Keypress KEsc :: Keypress KBS :: Keypress KEnter :: Keypress KUnknown :: Keypress KLeft :: Keypress KRight :: Keypress KUp :: Keypress KDown :: Keypress -- | This represents each modifier key that could be pressed along with a -- key. data Mod Ctrl :: Mod Alt :: Mod Shift :: Mod instance GHC.Classes.Eq Rasa.Internal.Events.Keypress instance GHC.Show.Show Rasa.Internal.Events.Keypress instance GHC.Classes.Eq Rasa.Internal.Events.Mod instance GHC.Show.Show Rasa.Internal.Events.Mod instance GHC.Classes.Eq Rasa.Internal.Events.BufAdded instance GHC.Show.Show Rasa.Internal.Events.BufAdded instance GHC.Classes.Eq Rasa.Internal.Events.Exit instance GHC.Show.Show Rasa.Internal.Events.Exit instance GHC.Classes.Eq Rasa.Internal.Events.AfterRender instance GHC.Show.Show Rasa.Internal.Events.AfterRender instance GHC.Classes.Eq Rasa.Internal.Events.OnRender instance GHC.Show.Show Rasa.Internal.Events.OnRender instance GHC.Classes.Eq Rasa.Internal.Events.BeforeRender instance GHC.Show.Show Rasa.Internal.Events.BeforeRender instance GHC.Classes.Eq Rasa.Internal.Events.BeforeEvent instance GHC.Show.Show Rasa.Internal.Events.BeforeEvent instance GHC.Classes.Eq Rasa.Internal.Events.Init instance GHC.Show.Show Rasa.Internal.Events.Init module Rasa.Internal.Range -- | (Coord Row Column) represents a char in a block of text. (zero -- indexed) e.g. Coord 0 0 is the first character in the text, Coord 2 1 -- is the second character of the third row data Coord Coord :: Int -> Int -> Coord -- | An Offset represents an exact position in a file as a number of -- characters from the start. newtype Offset Offset :: Int -> Offset -- | Given the text you're operating over, creates an iso from an -- Offset to a Coord. asCoord :: YiString -> Iso' Offset Coord -- | This will restrict a given Coord to a valid one which lies -- within the given text. clampCoord :: YiString -> Coord -> Coord -- | This will restrict a given Range to a valid one which lies -- within the given text. clampRange :: YiString -> Range -> Range -- | This represents a range between two coordinates (Coord) data Range Range :: Coord -> Coord -> Range -- | A lens over text which is encompassed by a Range range :: HasBuffer s => Range -> Lens' s YiString -- | Returns the number of rows and columns that a chunk of text spans as a -- Coord sizeOf :: YiString -> Coord -- | Returns the number of rows and columns that a Range spans as a -- Coord sizeOfR :: Range -> Coord -- | Moves a Range by a given Coord It may be unintuitive, -- but for (Coord row col) a given range will be moved down by row and to -- the right by col. moveRange :: Coord -> Range -> Range -- | Moves a range forward by the given amount moveRangeByN :: Int -> Range -> Range -- | Moves a Coord forward by the given amount of columns moveCursorByN :: Int -> Coord -> Coord -- | Adds the rows and columns of the given two Coords. moveCursor :: Coord -> Coord -> Coord -- | A span which maps a piece of Monoidal data over a range. data Span a Span :: Range -> a -> Span a [_getRange] :: Span a -> Range [_data] :: Span a -> a -- | Combines a list of spans containing some monoidal data into a list of -- offsets with with the data that applies from each Offset forwards. combineSpans :: forall a. Monoid a => [Span a] -> [(Coord, a)] -- | clamp min max val restricts val to be within min and max -- (inclusive) clamp :: Int -> Int -> Int -> Int -- | A lens over text before a given Coord beforeC :: Coord -> Lens' YiString YiString -- | A lens over text after a given Coord afterC :: Coord -> Lens' YiString YiString instance GHC.Classes.Eq Rasa.Internal.Range.Marker instance GHC.Show.Show Rasa.Internal.Range.Marker instance GHC.Base.Functor Rasa.Internal.Range.Span instance GHC.Classes.Eq a => GHC.Classes.Eq (Rasa.Internal.Range.Span a) instance GHC.Show.Show a => GHC.Show.Show (Rasa.Internal.Range.Span a) instance GHC.Classes.Eq Rasa.Internal.Range.Offset instance GHC.Show.Show Rasa.Internal.Range.Offset instance GHC.Classes.Eq Rasa.Internal.Range.Range instance GHC.Show.Show Rasa.Internal.Range.Range instance GHC.Classes.Eq Rasa.Internal.Range.Coord instance GHC.Show.Show Rasa.Internal.Range.Coord instance GHC.Classes.Ord Rasa.Internal.Range.Range instance GHC.Classes.Ord Rasa.Internal.Range.Coord instance GHC.Num.Num Rasa.Internal.Range.Coord module Rasa.Internal.Action -- | A wrapper around event listeners so they can be stored in -- Hooks. data Hook Hook :: HookId -> (a -> Action ()) -> Hook data HookId HookId :: Int -> TypeRep -> HookId -- | A map of Event types to a list of listeners for that event type Hooks = Map TypeRep [Hook] -- | This is a monad-transformer stack for performing actions against the -- editor. You register Actions to be run in response to events using -- onEveryTrigger -- -- Within an Action you can: -- -- newtype Action a Action :: StateT ActionState IO a -> Action a [runAct] :: Action a -> StateT ActionState IO a -- | Execute an Action (returning the editor state) execAction :: ActionState -> Action () -> IO ActionState -- | Evaluate an Action (returning the value) evalAction :: ActionState -> Action a -> IO a type AsyncAction = Async (Action ()) -- | This contains all data representing the editor's state. It acts as the -- state object for an 'Action data ActionState ActionState :: Editor -> [AsyncAction] -> Hooks -> Int -> ActionState [_ed] :: ActionState -> Editor [_asyncs] :: ActionState -> [AsyncAction] [_hooks] :: ActionState -> Hooks [_nextHook] :: ActionState -> Int nextHook :: Lens' ActionState Int hooks :: Lens' ActionState Hooks ed :: Lens' ActionState Editor asyncs :: Lens' ActionState [AsyncAction] -- | Allows polymorphic lenses which need to access something in -- ActionState class HasActionState a actionState :: HasActionState a => Lens' a ActionState -- | Contains all data about the editor; as well as a buffer which is in -- focus. We keep the full ActionState here too so that -- Actions may be lifted inside a BufAction data BufActionState BufActionState :: ActionState -> Buffer -> BufActionState [_actState] :: BufActionState -> ActionState [_buf] :: BufActionState -> Buffer buf :: Lens' BufActionState Buffer actState :: Lens' BufActionState ActionState -- | This is a monad-transformer stack for performing actions on a specific -- buffer. You run BufActions by embedding them in a Action -- via bufferDo or buffersDo -- -- Within a BufAction you can: -- -- newtype BufAction a BufAction :: StateT BufActionState IO a -> BufAction a [runBufAct] :: BufAction a -> StateT BufActionState IO a -- | This lifts up a bufAction into an Action which performs the -- BufAction over the referenced buffer and returns the result (if -- the buffer existed) liftBuf :: BufAction a -> BufRef -> Action (Maybe a) -- | This lifts up an Action to be run inside a BufAction -- -- it is your responsibility to ensure that any nested Actions -- don't edit the Buffer which the current BufAction is editing; -- behaviour is undefined if this occurs. liftAction :: Action a -> BufAction a instance Control.Monad.IO.Class.MonadIO Rasa.Internal.Action.BufAction instance Control.Monad.State.Class.MonadState Rasa.Internal.Action.BufActionState Rasa.Internal.Action.BufAction instance GHC.Base.Monad Rasa.Internal.Action.BufAction instance GHC.Base.Applicative Rasa.Internal.Action.BufAction instance GHC.Base.Functor Rasa.Internal.Action.BufAction instance GHC.Show.Show Rasa.Internal.Action.ActionState instance Rasa.Internal.Buffer.HasBuffer Rasa.Internal.Action.BufActionState instance Rasa.Internal.Action.HasActionState Rasa.Internal.Action.BufActionState instance Rasa.Internal.Action.HasActionState Rasa.Internal.Action.ActionState instance Rasa.Internal.Editor.HasEditor Rasa.Internal.Action.ActionState instance Data.Default.Class.Default Rasa.Internal.Action.ActionState instance Control.Monad.IO.Class.MonadIO Rasa.Internal.Action.Action instance Control.Monad.State.Class.MonadState Rasa.Internal.Action.ActionState Rasa.Internal.Action.Action instance GHC.Base.Monad Rasa.Internal.Action.Action instance GHC.Base.Applicative Rasa.Internal.Action.Action instance GHC.Base.Functor Rasa.Internal.Action.Action instance GHC.Classes.Eq Rasa.Internal.Action.HookId module Rasa.Internal.Scheduler -- | A wrapper around event listeners so they can be stored in -- Hooks. data Hook -- | A map of Event types to a list of listeners for that event type Hooks = Map TypeRep [Hook] -- | This registers an event listener hook, as long as the listener is -- well-typed similar to this: -- -- MyEventType -> Action () then it will be triggered on all -- dispatched events of that type. It returns an ID which may be used -- with removeListener to cancel the listener onEveryTrigger :: forall a. Typeable a => (a -> Action ()) -> Action HookId onEveryTrigger_ :: forall a. Typeable a => (a -> Action ()) -> Action () -- | This acts as onEveryTrigger but listens only for the first -- event of a given type. onNextEvent :: forall a. Typeable a => (a -> Action ()) -> Action () -- | Registers an action to be performed during the Initialization phase. -- -- This phase occurs exactly ONCE when the editor starts up. Though -- arbitrary actions may be performed in the configuration block; it's -- recommended to embed such actions in the onInit event listener so that -- all event listeners are registered before anything Actions occur. onInit :: Action () -> Action () -- | Registers an action to be performed BEFORE each event phase. beforeEveryEvent :: Action () -> Action HookId beforeEveryEvent_ :: Action () -> Action () beforeNextEvent :: Action () -> Action () -- | Registers an action to be performed BEFORE each render phase. -- -- This is a good spot to add information useful to the renderer since -- all actions have been performed. Only cosmetic changes should occur -- during this phase. beforeEveryRender :: Action () -> Action HookId beforeEveryRender_ :: Action () -> Action () beforeNextRender :: Action () -> Action () -- | Registers an action to be performed during each render phase. -- -- This phase should only be used by extensions which actually render -- something. onEveryRender :: Action () -> Action HookId onEveryRender_ :: Action () -> Action () onNextRender :: Action () -> Action () -- | Registers an action to be performed AFTER each render phase. -- -- This is useful for cleaning up extension state that was registered for -- the renderer, but needs to be cleared before the next iteration. afterEveryRender :: Action () -> Action HookId afterEveryRender_ :: Action () -> Action () afterNextRender :: Action () -> Action () -- | Use this to dispatch an event of any type, any hooks which are -- listening for this event will be triggered with the provided event. -- Use this within an Action. dispatchEvent :: Typeable a => a -> Action () -- | Registers an action to be performed during the exit phase. -- -- This is only triggered exactly once when the editor is shutting down. -- It allows an opportunity to do clean-up, kill any processes you've -- started, or save any data before the editor terminates. onExit :: Action () -> Action () -- | This removes a listener and prevents it from responding to any more -- events. removeListener :: HookId -> Action () -- | This extracts all event listener hooks from a map of hooks which match -- the type of the provided event. matchingHooks :: forall a. Typeable a => Hooks -> [a -> Action ()] -- | Registers an action to be performed after a new buffer is added. -- -- The supplied function will be called with a BufRef to the new -- buffer, and the resulting Action will be run. onBufAdded :: (BufRef -> Action ()) -> Action HookId module Rasa.Internal.Async -- | doAsync allows you to perform a task asynchronously and then apply the -- result. In doAsync asyncAction, asyncAction is an IO -- which resolves to an Action, note that the context in which the second -- action is executed is NOT the same context in which doAsync is called; -- it is likely that text and other state have changed while the IO -- executed, so it's a good idea to check (inside the applying Action) -- that things are in a good state before making changes. Here's an -- example: -- --
--   asyncCapitalize :: Action ()
--   asyncCapitalize = do
--     txt <- focusDo $ use text
--     -- We give doAsync an IO which resolves in an action
--     doAsync $ ioPart txt
--   
--   ioPart :: Text -> IO (Action ())
--   ioPart txt = do
--     result <- longAsyncronousCapitalizationProgram txt
--     -- Note that this returns an Action, but it's still wrapped in IO
--     return $ maybeApplyResult txt result
--   
--   maybeApplyResult :: Text -> Text -> Action ()
--   maybeApplyResult oldTxt capitalized = do
--     -- We get the current buffer's text, which may have changed since we started
--     newTxt <- focusDo (use text)
--     if newTxt == oldTxt
--       -- If the text is the same as it was, we can apply the transformation
--       then focusDo (text .= capitalized)
--       -- Otherwise we can choose to re-queue the whole action and try again
--       -- Or we could just give up.
--       else asyncCapitalize
--   
doAsync :: IO (Action ()) -> Action () -- | This function takes an IO which results in some Event, it runs the IO -- asynchronously and dispatches the event, then repeats the process all -- over again. Use this inside the onInit scheduler to register an event -- listener for some event (e.g. keypresses or network activity) eventProvider :: Typeable a => IO a -> Action () module Rasa.Internal.Directive -- | This lifts a BufAction to an Action which performs the -- BufAction on the buffer referred to by the BufRef If the -- buffer referred to no longer exists this returns Action -- Nothing. bufDo :: BufRef -> BufAction a -> Action (Maybe a) bufDo_ :: BufRef -> BufAction a -> Action () -- | This lifts a BufAction to an Action which performs the -- BufAction on every buffer and collects the return values as a -- list. buffersDo :: BufAction a -> Action [a] buffersDo_ :: BufAction a -> Action () -- | This signals to the editor that you'd like to shutdown. The current -- events will finish processing, then the onExit hook will run, -- then the editor will exit. exit :: Action () -- | This adds a new buffer with the given text. newBuffer :: YiString -> Action BufRef -- | Returns an up-to-date list of all BufRefs getBufRefs :: Action [BufRef] -- | Returns an up-to-date list of all Buffers, returned values are -- read-only; altering them has no effect on the actual stored buffers. -- This function is useful for renderers. getBuffers :: Action [(BufRef, Buffer)] -- | Returns the Buffer for a BufRef if it still exists. This is -- read-only; altering the buffer has no effect on the stored buffer. -- This function is useful for renderers. getBuffer :: BufRef -> Action (Maybe Buffer) -- | Gets BufRef that comes after the one provided nextBufRef :: BufRef -> Action BufRef -- | Gets BufRef that comes before the one provided prevBufRef :: BufRef -> Action BufRef -- | Runs the given function over the text in the range, replacing it with -- the results. overRange :: Range -> (YiString -> YiString) -> BufAction () -- | Replaces the text in the given range from the buffer. replaceRange :: Range -> YiString -> BufAction () -- | Deletes the text in the given range from the buffer. deleteRange :: Range -> BufAction () -- | Inserts text into the buffer at the given Coord. insertAt :: Coord -> YiString -> BufAction () -- | Returns the number of rows and columns that a chunk of text spans as a -- Coord sizeOf :: YiString -> Coord -- | This module contains the public API for building an extension for -- Rasa. It re-exports the parts of rasa that are public API for creating -- extensions. -- -- There are two main things that an extension can do, either react to -- editor events, or expose useful actions and/or state for other -- extensions to use. -- -- Whether performing its own actions or being used by a different -- extension an extension will want to define some Actions to -- perform. Actions can operate over buffers or even perform IO and -- comprise the main way in which extensons do what they need to do. Read -- more here: Action, BufAction. -- -- To sum it all up, Here's an example of a simple logging extension that -- simply writes each keypress to a file. -- --
--   logKeypress :: Keypress -> Action ()
--   logKeypress (Keypress char _) = liftIO $ appendFile "logs" ("You pressed " ++ [char] ++ "\n")
--   
--   logger :: Action HookId
--   logger = do
--     onInit $ liftIO $ writeFile "logs" "==Logs==\n"
--     onEveryTrigger_ logKeypress
--     onExit $ liftIO $ appendFile "logs" "==Done=="
--   
-- -- Check out this tutorial on building extensions, it's also just a great -- way to learn how the editor works: -- <https://github.com/ChrisPenner/rasa/blob/master/docs/Building-An-Extension.md -- Building an Extension>. module Rasa.Ext -- | This is a monad-transformer stack for performing actions against the -- editor. You register Actions to be run in response to events using -- onEveryTrigger -- -- Within an Action you can: -- -- data Action a -- | doAsync allows you to perform a task asynchronously and then apply the -- result. In doAsync asyncAction, asyncAction is an IO -- which resolves to an Action, note that the context in which the second -- action is executed is NOT the same context in which doAsync is called; -- it is likely that text and other state have changed while the IO -- executed, so it's a good idea to check (inside the applying Action) -- that things are in a good state before making changes. Here's an -- example: -- --
--   asyncCapitalize :: Action ()
--   asyncCapitalize = do
--     txt <- focusDo $ use text
--     -- We give doAsync an IO which resolves in an action
--     doAsync $ ioPart txt
--   
--   ioPart :: Text -> IO (Action ())
--   ioPart txt = do
--     result <- longAsyncronousCapitalizationProgram txt
--     -- Note that this returns an Action, but it's still wrapped in IO
--     return $ maybeApplyResult txt result
--   
--   maybeApplyResult :: Text -> Text -> Action ()
--   maybeApplyResult oldTxt capitalized = do
--     -- We get the current buffer's text, which may have changed since we started
--     newTxt <- focusDo (use text)
--     if newTxt == oldTxt
--       -- If the text is the same as it was, we can apply the transformation
--       then focusDo (text .= capitalized)
--       -- Otherwise we can choose to re-queue the whole action and try again
--       -- Or we could just give up.
--       else asyncCapitalize
--   
doAsync :: IO (Action ()) -> Action () -- | This signals to the editor that you'd like to shutdown. The current -- events will finish processing, then the onExit hook will run, -- then the editor will exit. exit :: Action () -- | This adds a new buffer with the given text. newBuffer :: YiString -> Action BufRef -- | Gets BufRef that comes after the one provided nextBufRef :: BufRef -> Action BufRef -- | Gets BufRef that comes before the one provided prevBufRef :: BufRef -> Action BufRef -- | Returns an up-to-date list of all BufRefs getBufRefs :: Action [BufRef] -- | Returns an up-to-date list of all Buffers, returned values are -- read-only; altering them has no effect on the actual stored buffers. -- This function is useful for renderers. getBuffers :: Action [(BufRef, Buffer)] -- | Returns the Buffer for a BufRef if it still exists. This is -- read-only; altering the buffer has no effect on the stored buffer. -- This function is useful for renderers. getBuffer :: BufRef -> Action (Maybe Buffer) -- | This is a monad-transformer stack for performing actions on a specific -- buffer. You run BufActions by embedding them in a Action -- via bufferDo or buffersDo -- -- Within a BufAction you can: -- -- data BufAction a -- | This lifts up an Action to be run inside a BufAction -- -- it is your responsibility to ensure that any nested Actions -- don't edit the Buffer which the current BufAction is editing; -- behaviour is undefined if this occurs. liftAction :: Action a -> BufAction a -- | This lifts a BufAction to an Action which performs the -- BufAction on the buffer referred to by the BufRef If the -- buffer referred to no longer exists this returns Action -- Nothing. bufDo :: BufRef -> BufAction a -> Action (Maybe a) bufDo_ :: BufRef -> BufAction a -> Action () -- | This lifts a BufAction to an Action which performs the -- BufAction on every buffer and collects the return values as a -- list. buffersDo :: BufAction a -> Action [a] buffersDo_ :: BufAction a -> Action () -- | Runs the given function over the text in the range, replacing it with -- the results. overRange :: Range -> (YiString -> YiString) -> BufAction () -- | Replaces the text in the given range from the buffer. replaceRange :: Range -> YiString -> BufAction () -- | Deletes the text in the given range from the buffer. deleteRange :: Range -> BufAction () -- | Inserts text into the buffer at the given Coord. insertAt :: Coord -> YiString -> BufAction () -- | Returns the number of rows and columns that a chunk of text spans as a -- Coord sizeOf :: YiString -> Coord -- | ext is a lens which will focus the extension state that matches -- the type inferred as the focal point. It's a little bit of magic, if -- you treat the focus as a member of your extension state it should just -- work out. -- -- This lens falls back on the extension's Default instance (when -- getting) if nothing has yet been stored. ext :: forall a e. (Show a, Typeable a, Default a, HasEditor e) => Lens' e a -- | bufExt is a lens which will focus a given extension's state -- within a buffer (within a BufAction). The lens will -- automagically focus the required extension by using type inference. -- It's a little bit of magic, if you treat the focus as a member of your -- extension state it should just work out. -- -- This lens falls back on the extension's Default instance (when -- getting) if nothing has yet been stored. bufExt :: forall a s. (Show a, Typeable a, Default a, HasBuffer s) => Lens' s a -- | A buffer, holds the text in the buffer and any extension states that -- are set on the buffer. data Buffer -- | This allows creation of polymorphic lenses over any type which has -- access to a Buffer class HasBuffer a -- | An opaque reference to a buffer (The contained Int is not meant to be -- altered). It is possible for references to become stale if buffers are -- deleted. Operations over invalid BufRef's are simply ignored and -- return Nothing if a value was expected. data BufRef -- | This allows polymorphic lenses over anything that has access to an -- Editor context class HasEditor a -- | This lens focuses the text of the in-scope buffer. text :: HasBuffer b => Lens' b YiString -- | This event is dispatched in response to keyboard key presses. It -- contains both the char that was pressed and any modifiers (Mod) -- that where held when the key was pressed. data Keypress Keypress :: Char -> [Mod] -> Keypress KEsc :: Keypress KBS :: Keypress KEnter :: Keypress KUnknown :: Keypress KLeft :: Keypress KRight :: Keypress KUp :: Keypress KDown :: Keypress -- | This represents each modifier key that could be pressed along with a -- key. data Mod Ctrl :: Mod Alt :: Mod Shift :: Mod -- | A map of Event types to a list of listeners for that event type Hooks = Map TypeRep [Hook] -- | A wrapper around event listeners so they can be stored in -- Hooks. data Hook data HookId -- | Use this to dispatch an event of any type, any hooks which are -- listening for this event will be triggered with the provided event. -- Use this within an Action. dispatchEvent :: Typeable a => a -> Action () -- | This registers an event listener hook, as long as the listener is -- well-typed similar to this: -- -- MyEventType -> Action () then it will be triggered on all -- dispatched events of that type. It returns an ID which may be used -- with removeListener to cancel the listener onEveryTrigger :: forall a. Typeable a => (a -> Action ()) -> Action HookId onEveryTrigger_ :: forall a. Typeable a => (a -> Action ()) -> Action () -- | This acts as onEveryTrigger but listens only for the first -- event of a given type. onNextEvent :: forall a. Typeable a => (a -> Action ()) -> Action () -- | This removes a listener and prevents it from responding to any more -- events. removeListener :: HookId -> Action () -- | This function takes an IO which results in some Event, it runs the IO -- asynchronously and dispatches the event, then repeats the process all -- over again. Use this inside the onInit scheduler to register an event -- listener for some event (e.g. keypresses or network activity) eventProvider :: Typeable a => IO a -> Action () -- | Registers an action to be performed during the Initialization phase. -- -- This phase occurs exactly ONCE when the editor starts up. Though -- arbitrary actions may be performed in the configuration block; it's -- recommended to embed such actions in the onInit event listener so that -- all event listeners are registered before anything Actions occur. onInit :: Action () -> Action () -- | Registers an action to be performed BEFORE each event phase. beforeEveryEvent :: Action () -> Action HookId beforeEveryEvent_ :: Action () -> Action () beforeNextEvent :: Action () -> Action () -- | Registers an action to be performed BEFORE each render phase. -- -- This is a good spot to add information useful to the renderer since -- all actions have been performed. Only cosmetic changes should occur -- during this phase. beforeEveryRender :: Action () -> Action HookId beforeEveryRender_ :: Action () -> Action () beforeNextRender :: Action () -> Action () -- | Registers an action to be performed during each render phase. -- -- This phase should only be used by extensions which actually render -- something. onEveryRender :: Action () -> Action HookId onEveryRender_ :: Action () -> Action () onNextRender :: Action () -> Action () -- | Registers an action to be performed AFTER each render phase. -- -- This is useful for cleaning up extension state that was registered for -- the renderer, but needs to be cleared before the next iteration. afterEveryRender :: Action () -> Action HookId afterEveryRender_ :: Action () -> Action () afterNextRender :: Action () -> Action () -- | Registers an action to be performed during the exit phase. -- -- This is only triggered exactly once when the editor is shutting down. -- It allows an opportunity to do clean-up, kill any processes you've -- started, or save any data before the editor terminates. onExit :: Action () -> Action () -- | Registers an action to be performed after a new buffer is added. -- -- The supplied function will be called with a BufRef to the new -- buffer, and the resulting Action will be run. onBufAdded :: (BufRef -> Action ()) -> Action HookId -- | This represents a range between two coordinates (Coord) data Range Range :: Coord -> Coord -> Range -- | (Coord Row Column) represents a char in a block of text. (zero -- indexed) e.g. Coord 0 0 is the first character in the text, Coord 2 1 -- is the second character of the third row data Coord Coord :: Int -> Int -> Coord -- | An Offset represents an exact position in a file as a number of -- characters from the start. newtype Offset Offset :: Int -> Offset -- | A span which maps a piece of Monoidal data over a range. data Span a Span :: Range -> a -> Span a [_getRange] :: Span a -> Range [_data] :: Span a -> a -- | Combines a list of spans containing some monoidal data into a list of -- offsets with with the data that applies from each Offset forwards. combineSpans :: forall a. Monoid a => [Span a] -> [(Coord, a)] -- | Given the text you're operating over, creates an iso from an -- Offset to a Coord. asCoord :: YiString -> Iso' Offset Coord -- | This will restrict a given Coord to a valid one which lies -- within the given text. clampCoord :: YiString -> Coord -> Coord -- | This will restrict a given Range to a valid one which lies -- within the given text. clampRange :: YiString -> Range -> Range -- | A lens over text which is encompassed by a Range range :: HasBuffer s => Range -> Lens' s YiString -- | Returns the number of rows and columns that a Range spans as a -- Coord sizeOfR :: Range -> Coord -- | A lens over text after a given Coord afterC :: Coord -> Lens' YiString YiString -- | A lens over text before a given Coord beforeC :: Coord -> Lens' YiString YiString -- | Moves a Range by a given Coord It may be unintuitive, -- but for (Coord row col) a given range will be moved down by row and to -- the right by col. moveRange :: Coord -> Range -> Range -- | Moves a range forward by the given amount moveRangeByN :: Int -> Range -> Range -- | Moves a Coord forward by the given amount of columns moveCursorByN :: Int -> Coord -> Coord -- | An iso which converts to/from YiString -> Text asText :: Iso' YiString Text -- | An iso which converts to/from YiString -> String asString :: Iso' YiString String -- | An iso which converts to/from YiString -> [YiString] asLines :: Iso' YiString [YiString] -- | clamp min max val restricts val to be within min and max -- (inclusive) clamp :: Int -> Int -> Int -> Int module Rasa -- | The main function to run rasa. -- --
--   rasa eventProviders extensions
--   
-- -- This should be imported by a user-config with and called with an -- Action containing any extensions which have event listeners. -- --
--   rasa $ do
--     cursor
--     vim
--     slate
--   
rasa :: Action () -> IO ()