Copyright | (c) Sebastian Witte |
---|---|
License | Apache-2.0 |
Maintainer | woozletoff@gmail.com |
Stability | experimental |
Portability | GHC (due to Template Haskell) |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module should contain all the things you need to write neovim plugins in
your favorite language! :-)
The documentation in this module should provide every information you need to start writing plugins.
Synopsis
- data Neovim env a
- neovim :: NeovimConfig -> IO ()
- data NeovimConfig = Config {
- plugins :: [Neovim () NeovimPlugin]
- logOptions :: Maybe (FilePath, Priority)
- defaultConfig :: NeovimConfig
- def :: Default a => a
- data NeovimPlugin = forall env. NeovimPlugin (Plugin env)
- data Plugin env = Plugin {
- environment :: env
- exports :: [ExportedFunctionality env]
- class NFData o => NvimObject o where
- toObject :: o -> Object
- fromObjectUnsafe :: Object -> o
- fromObject :: Object -> Either (Doc AnsiStyle) o
- fromObject' :: MonadIO io => Object -> io o
- (+:) :: NvimObject o => o -> [Object] -> [Object]
- type Dictionary = Map ByteString Object
- data Object
- wrapPlugin :: Applicative m => Plugin env -> m NeovimPlugin
- function :: String -> Name -> Q Exp
- function' :: Name -> Q Exp
- command :: String -> Name -> Q Exp
- command' :: Name -> Q Exp
- autocmd :: Name -> Q Exp
- data Synchronous
- data CommandOption
- data RangeSpecification
- data CommandArguments = CommandArguments {}
- data AutocmdOptions = AutocmdOptions {
- acmdPattern :: String
- acmdNested :: Bool
- acmdGroup :: Maybe String
- addAutocmd :: ByteString -> Synchronous -> AutocmdOptions -> Neovim env () -> Neovim env (Maybe (Either (Neovim anyEnv ()) ReleaseKey))
- ask :: MonadReader r m => m r
- asks :: MonadReader r m => (r -> a) -> m a
- data Subscription
- subscribe :: Text -> ([Object] -> Neovim env ()) -> Neovim env Subscription
- unsubscribe :: Subscription -> Neovim env ()
- newtype NeovimEventId = NeovimEventId Text
- wait :: Neovim env (STM result) -> Neovim env result
- wait' :: Neovim env (STM result) -> Neovim env ()
- err :: Doc AnsiStyle -> Neovim env a
- errOnInvalidResult :: NvimObject o => Neovim env (Either NeovimException Object) -> Neovim env o
- catchNeovimException :: MonadUnliftIO io => io a -> (NeovimException -> io a) -> io a
- data NeovimException
- liftIO :: MonadIO m => IO a -> m a
- whenM :: Monad m => m Bool -> m () -> m ()
- unlessM :: Monad m => m Bool -> m () -> m ()
- docToObject :: Doc AnsiStyle -> Object
- docFromObject :: Object -> Either (Doc AnsiStyle) (Doc AnsiStyle)
- data Doc ann
- data AnsiStyle
- class Pretty a where
- pretty :: a -> Doc ann
- prettyList :: [a] -> Doc ann
- putDoc :: Doc AnsiStyle -> IO ()
- exceptionToDoc :: NeovimException -> Doc AnsiStyle
- data Priority
- void :: Functor f => f a -> f ()
- module Control.Applicative
- module Data.Monoid
- data Int8
- data Int16
- data Int32
- data Int64
- data Word
- data Word8
- data Word16
- data Word32
Installation
Installation instructions are in the README.md file that comes with the source of this package. It is also on the repositories front page.
Tutorial
Motivation
An nvim-hs
plugin is just a collection of haskell functions that can be
called from neovim.
As a user of plugins, you basically have two choices. You can start every plugin in a separate process and use normal vim plugin management strategies such as vim-plug or pathogen. Alternatively, you can create a haskell project and depend on the plugins you want to use and plumb them together. This plumbing is equivalent to writing a plugin.
Since you are reading haddock documentation, you probably want the latter, so
just keep reading. :-)
The easiest way to start is to use the stack template as described in the
README.md
of this package. If you initialize it in your neovim configuration
directory (~/.config/nvim
on linux-based systems), it should automatically be
compiled and run with two simple example plugins.
You have to define a haskell project that depends on this package and contains an executable secion within a main file that looks something like this:
import TestPlugin.ExamplePlugin (examplePlugin) main =neovim
def
{plugins
= [ examplePlugin ] ++plugins
defaultConfig
}
nvim-hs is all about importing and creating plugins. This is done following a
concise API. Let's start by making a given plugin available inside
our plugin provider. Assuming that we have installed a cabal package that exports
an examplePlugin
from the module TestPlugin.ExamplePlugin
, a minimal
main file would look something like this:
That's all you have to do! Multiple plugins are simply imported and put in a list.
This is the environment in which all plugins are initially started.
Functions have to run in this transformer stack to communicate with neovim.
If parts of your own functions dont need to communicate with neovim, it is
good practice to factor them out. This allows you to write tests and spot
errors easier. Essentially, you should treat this similar to IO
in general
haskell programs.
Instances
MonadReader env (Neovim env) Source # | User facing instance declaration for the reader state. |
MonadFail (Neovim env) Source # | |
Defined in Neovim.Context.Internal | |
MonadIO (Neovim env) Source # | |
Defined in Neovim.Context.Internal | |
Applicative (Neovim env) Source # | |
Defined in Neovim.Context.Internal | |
Functor (Neovim env) Source # | |
Monad (Neovim env) Source # | |
MonadThrow (Neovim env) Source # | |
Defined in Neovim.Context.Internal | |
MonadResource (Neovim env) Source # | |
Defined in Neovim.Context.Internal liftResourceT :: ResourceT IO a -> Neovim env a # | |
MonadUnliftIO (Neovim env) Source # | |
Defined in Neovim.Context.Internal | |
Monoid a => Monoid (Neovim env a) Source # | |
Semigroup a => Semigroup (Neovim env a) Source # | |
neovim :: NeovimConfig -> IO () Source #
This is essentially the main function for nvim-hs, at least if you want to use Config.Dyre for the configuration.
data NeovimConfig Source #
This data type contains information about the configuration of neovim. See the fields' documentation for what you possibly want to change. Also, the tutorial in the Neovim module should get you started.
Config | |
|
defaultConfig :: NeovimConfig Source #
Default configuration options for nvim-hs. If you want to keep the default plugins enabled, you can define your config like this:
main =neovim
defaultConfig
{ plugins = plugins defaultConfig ++ myPlugins }
Creating a plugin
Creating plugins isn't difficult either. You just have to follow and survive the
compile time errors of seemingly valid code. This may sound scary, but it is not
so bad. We will cover most pitfalls in the following paragraphs and if there
isn't a solution for your error, you can always ask any friendly Haskeller in
#haskell on irc.freenode.net
!
Enough scary stuff said for now, let's write a plugin!
Due to a stage restriction in GHC when using Template Haskell
(i.e. code generation), we must define
our functions in a different module than $XDG_CONFIG_HOME/nvim/nvim.hs
.
(I'm assuming here, that you use $XDG_CONFIG_HOME/nvim/
as the base
directory for historical reasons and because it might be an appropriate place.)
This is a bit unfortunate, but it will save you a lot of boring boilerplate and
it will present you with helpful error messages if your plugin's functions do
not work together with neovim.
So, let's write a plugin that calculates the n
th Fibonacci number. Don't we all
love those!
File ~/.config/nvim/lib/Fibonacci/Plugin.hs
:
module Fibonacci.Plugin (fibonacci) where import Neovim -- | Neovim is not really good with big numbers, so we return aString
here. fibonacci ::Int
->Neovim
envString
fibonacci n =return
.show
$ fibs !! n where fibs :: [Integer] fibs = 0:1:scanl1
(+) fibs
File ~/.config/nvim/lib/Fibonacci.hs
:
{-# LANGUAGE TemplateHaskell #-} module Fibonacci (plugin) where import Neovim import Fibonacci.Plugin (fibonacci) plugin ::Neovim
()NeovimPlugin
plugin =wrapPlugin
Plugin {environment
= () ,exports
= [ $(function'
'fibonacci)Sync
] }
File ~/.config/nvim/nvim.hs
:
import Neovim import qualified Fibonacci as Fibonacci main ::IO
() main =neovim
defaultConfig
{plugins
=plugins
defaultConfig
++ [ Fibonacci.plugin ] }
Let's analyze how it works. The module Fibonacci.Plugin
simply defines a function
that takes the n
th element of the infinite list of Fibonacci numbers. Even though
the definition is very concise and asthetically pleasing, the important part is the
type signature for fibonacci
. Similarly how main :: IO ()
works in normal Haskell
programs, Neovim
is the environment we need for plugins. Internally, it stores a
few things that are needed to communicate with neovim, but that shouldn't bother you
too much. Simply remember that every plugin function must have a function signature
whose last element is of type
. The result of Neovim
env somethingfibonacci
is String
because neovim cannot handle big numbers so well. :-)
You can use any argument or result type as long as it is an instance of NvimObject
.
The second part of of the puzzle, which is the definition of plugin
in ~/.config/nvim/lib/Fibonacci.hs
, shows what a plugin is. It is essentially
an empty environment and a list of functions, commands or autocommands in the context of vim
terminology. In the end, all of those things map to a function at the side
of nvim-hs. If you really want to know what the distinction between those is, you
have to consult the :help
pages of neovim (e.g. :help :function
, :help :command
and :help :autocmd
). What's relevant from the side of nvim-hs is the environment.
The environment is a data type that is avaiable to all exported functions of your
plugin. This example does not make use of anything of that environment, so
we used ()
, also known as unit, as our environment. The definition of
fibonacci
uses a type variable env
as it does not access the environment and
can handle any environment. If you want to access the environment, you can call
ask
or asks
if you are inside a Neovim
environment. An example that shows
you how to use it can be found in a later chapter.
Now to the magical part: $(
. This is a so called
Template Haskell splice and this is why you need
function'
'fibonacci){-# LANGUAGE TemplateHaskell #-}
at the top of your Haskell file. This
splice simply generates Haskell code that, in this case, still needs a value
of type Synchronous
which indicates whether calling the function will make
neovim wait for its result or not. Internally, the expression
$(
creates a value that contains all the
necessary information to properly register the function with neovim. Note the
prime symbol before the function name! This would have probably caused you
some trouble if I haven't mentioned it here! Template Haskell simply requires
you to put that in front of function names that are passed in a splice.function'
'fibonacci) Sync
If you compile this and restart the plugin, you can calculate the 2000th Fibonacci number like as if it were a normal vim-script function:
:echo Fibonacci(2000)
You can also directly insert the result inside any text file opened with neovim by using the evaluation register by pressing the following key sequence in insert mode:
<C-r>=Fibonacci(2000)
The haddock documentation will now list all the things we have used up until now. Afterwards, there is a plugin with state which uses the environment.
data NeovimPlugin Source #
Plugin
values are wraped inside this data type via wrapPlugin
so that
we can put plugins in an ordinary list.
forall env. NeovimPlugin (Plugin env) |
This data type contains meta information for the plugin manager.
Plugin | |
|
class NFData o => NvimObject o where Source #
Conversion from Object
files to Haskell types and back with respect
to neovim's interpretation.
The NFData
constraint has been added to allow forcing results of function
evaluations in order to catch exceptions from pure code. This adds more
stability to the plugin provider and seems to be a cleaner approach.
toObject :: o -> Object Source #
fromObjectUnsafe :: Object -> o Source #
fromObject :: Object -> Either (Doc AnsiStyle) o Source #
fromObject' :: MonadIO io => Object -> io o Source #
Instances
(+:) :: NvimObject o => o -> [Object] -> [Object] infixr 5 Source #
Convenient operator to create a list of Object
from normal values.
values +: of :+ different :+ types :+ can +: be +: combined +: this +: way +: []
type Dictionary = Map ByteString Object Source #
A generic vim dictionary is a simply a map from strings to objects. This type alias is sometimes useful as a type annotation especially if the OverloadedStrings extension is enabled.
ObjectNil | |
ObjectUInt Word64 | Unsigned integers from the MsgPack protocol: uint 8, uint 16, uint 32, uint 64 |
ObjectInt Int64 | Signed integers and fixnums from the MsgPack protocol: positive fixnum, negative fixnum, int 8, int 16, int 32, int 64 |
ObjectBool Bool | |
ObjectFloat Float | |
ObjectDouble Double | |
ObjectString ByteString | |
ObjectBinary ByteString | |
ObjectArray [Object] | |
ObjectMap (Map Object Object) | |
ObjectExt !Int8 ByteString |
Instances
wrapPlugin :: Applicative m => Plugin env -> m NeovimPlugin Source #
Wrap a Plugin
in some nice blankets, so that we can put them in a simple
list.
function :: String -> Name -> Q Exp Source #
Define an exported function by providing a custom name and referencing the function you want to export.
Note that the name must start with an upper case letter.
Example: $(function "MyExportedFunction" 'myDefinedFunction)
Sync
function' :: Name -> Q Exp Source #
Define an exported function. This function works exactly like function
,
but it generates the exported name automatically by converting the first
letter to upper case.
command :: String -> Name -> Q Exp Source #
Similarly to function
, this function is used to export a command with a
custom name.
Note that commands must start with an upper case letter.
Due to limitations on the side of (neo)vim, commands can only have one of the
following five signatures, where you can replace String
with ByteString
or Text
if you wish:
CommandArguments
->Neovim
env ()CommandArguments
->Maybe
String
->Neovim
env ()CommandArguments
->String
->Neovim
env ()CommandArguments
-> [String
] ->Neovim
env ()CommandArguments
->String
-> [String
] ->Neovim
env ()
Example: $(command "RememberThePrime" 'someFunction) [
CmdBang
]
Note that the list of command options (i.e. the last argument) removes duplicate options by means of some internally convenient sorting. You should simply not define the same option twice.
command' :: Name -> Q Exp Source #
Define an exported command. This function works exactly like command
, but
it generates the command name by converting the first letter to upper case.
data Synchronous Source #
This option detemines how neovim should behave when calling some functionality on a remote host.
Async | Call the functionality entirely for its side effects and do not wait for it to finish. Calling a functionality with this flag set is completely asynchronous and nothing is really expected to happen. This is why a call like this is called notification on the neovim side of things. |
Sync | Call the function and wait for its result. This is only synchronous on the neovim side. This means that the GUI will (probably) not allow any user input until a reult is received. |
Instances
data CommandOption Source #
Options for commands.
Some command can also be described by using the OverloadedString extensions.
This means that you can write a literal String
inside your source file in
place for a CommandOption
value. See the documentation for each value on
how these strings should look like (Both versions are compile time checked.)
CmdSync Synchronous | Stringliteral "sync" or "async" |
CmdRegister | Register passed to the command. Stringliteral: |
CmdRange RangeSpecification | Determines how neovim passes the range. Stringliterals: "%" for |
CmdCount Word | Command handles a count. The argument defines the default count. Stringliteral: string of numbers (e.g. "132") |
CmdBang | Command handles a bang Stringliteral: "!" |
Instances
data RangeSpecification Source #
Specification of a range that acommand can operate on.
CurrentLine | The line the cursor is at when the command is invoked. |
WholeFile | Let the command operate on every line of the file. |
RangeCount Int | Let the command operate on each line in the given range. |
Instances
data CommandArguments Source #
You can use this type as the first argument for a function which is intended to be exported as a command. It holds information about the special attributes a command can take.
CommandArguments | |
|
Instances
data AutocmdOptions Source #
Options that can be used to register an autocmd. See :h :autocmd
or any
referenced neovim help-page from the fields of this data type.
AutocmdOptions | |
|
Instances
:: ByteString | The event to register to (e.g. BufWritePost) |
-> Synchronous | |
-> AutocmdOptions | |
-> Neovim env () | Fully applied function to register |
-> Neovim env (Maybe (Either (Neovim anyEnv ()) ReleaseKey)) | A |
Register an autocmd in the current context. This means that, if you are currently in a stateful plugin, the function will be called in the current thread and has access to the configuration and state of this thread. .
Note that the function you pass must be fully applied.
ask :: MonadReader r m => m r #
Retrieves the monad environment.
:: MonadReader r m | |
=> (r -> a) | The selector function to apply to the environment. |
-> m a |
Retrieves a function of the current environment.
Subscribing to notifications or events
data Subscription Source #
subscribe :: Text -> ([Object] -> Neovim env ()) -> Neovim env Subscription Source #
Subscribe to an event. When the event is received, the given callback function
is run. It is usually necessary to call the appropriate API function in order for
neovim to send the notifications to nvim-hs. The returned subscription can be
used to unsubscribe
.
unsubscribe :: Subscription -> Neovim env () Source #
Remove the subscription that has been returned by subscribe
.
newtype NeovimEventId Source #
Instances
Creating a stateful plugin
Now that we are a little bit comfortable with the interface provided by nvim-hs, we can start to write a more complicated plugin. Let's create a random number generator!
File ~/.config/nvim/lib/Random/Plugin.hs
:
module Random.Plugin (nextRandom, setNextRandom) where import Neovim import System.Random (newStdGen, randoms) import UnliftIO.STM (TVar, atomically, readTVar, modifyTVar, newTVarIO) -- You may want to define a type alias for your plugin, so that if you change -- your environment, you don't have to change all type signatures. -- -- If I were to write a real plugin, I would probably also create a data type -- instead of directly using a TVar here. -- type MyNeovim a = Neovim (TVar
[Int16
]) a -- This function will create an initial environment for our random number -- generator. Note that the return type is the type of our environment. randomNumbers :: Neovim startupEnv (TVar [Int16]) randomNumbers = do g <- liftIO newStdGen -- Create a new seed for a pseudo random number generator newTVarIO (randoms g) -- Put an infinite list of random numbers into a TVar -- | Get the next random number and update the state of the list. nextRandom :: MyNeovimInt16
nextRandom = do tVarWithRandomNumbers <-ask
atomically $ do -- pick the head of our list of random numbers r <-head
$readTVar
tVarWithRandomNumbers -- Since we do not want to return the same number all over the place -- remove the head of our list of random numbers modifyTVar tVarWithRandomNumberstail
return
r -- | You probably don't want this in a random number generator, but this shows -- hoy you can edit the state of a stateful plugin. setNextRandom ::Int16
-> MyNeovim () setNextRandom n = do tVarWithRandomNumbers <-ask
-- cons n to the front of the infinite list atomically $ modifyTVar tVarWithRandomNumbers (n:)
File ~/.config/nvim/lib/Random.hs
:
{-# LANGUAGE TemplateHaskell #-} module Random (plugin) where import Neovim import Random.Plugin (nextRandom, setNextRandom) import System.Random (newStdGen
,randoms
) plugin ::Neovim
(StartupConfig
NeovimConfig
) ()NeovimPlugin
plugin = do env <- randomNumberswrapPlugin
Plugin
{ environment = env ,exports
= [ $(function'
'nextRandom)Sync
, $(function
"SetNextRandom" 'setNextRandom)Async
] }
File ~/.config/nvim/nvim.hs
:
import Neovim import qualified Fibonacci as Fibonacci import qualified Random as Random main ::IO
() main =neovim
defaultConfig
{plugins
=plugins
defaultConfig
++ [ Fibonacci.plugin, Random.plugin ] }
That wasn't too hard, was it? The definition is very similar to the previous
example, we just were able to mutate our state and share that with other
functions. Another noteworthy detail, in case you
are not familiar with it, is the use of liftIO
in front of newStdGen
. You
have to do this, because newStdGen
has type
but the actions
inside the startup code are of type
IO
StdGen
. Neovim
() somethingliftIO
lifts an
IO
function so that it can be run inside the Neovim
context (or more
generally, any monad that implements the MonadIO
type class).
After you have saved these files (and removed any typos :-)
), you can restart
nvim-hs with :RestartNvimhs
and insert random numbers in your text files!
<C-r>=NextRandom()
You can also cheat and pretend you know the next number:
:call SetNextRandom(42)
Calling remote functions
Calling remote functions is only possible inside a Neovim
context. There are
a few patterns of return values for the available functions. Let's start with
getting some abstract Buffer
object, test whether it is valid and then try
to rename it.
inspectBuffer ::Neovim
env () inspectBuffer = do cb <-vim_get_current_buffer
isValid <-buffer_is_valid
cb when isValid $ do let newName = "magic" cbName <-wait'
$buffer_set_name
cb newName case () of _ | cbName == newName ->return
() _ ->err
$ "Renaming the current buffer failed!"
You may have noticed the wait'
function in there. Some functions have a return
type with STM
in it. This means that the function call is asynchronous. We can
wait
(or wait'
) for the result at the point at which we actually need it. In
this short example, we put the wait'
directly in front of the remote function
call because we want to inspect the result immediately, though. The other
functions either returned a result directly or they returned
whose result we inspected ourselves. The Either
Object
somethingerr
function directly terminates the current thread and sends the given error
message to neovim which the user immediately notices.
That's pretty much all there is to it.
wait :: Neovim env (STM result) -> Neovim env result Source #
Wait for the result of the STM action.
This action possibly blocks as it is an alias for
ioSTM -> ioSTM >>= liftIO . atomically
.
errOnInvalidResult :: NvimObject o => Neovim env (Either NeovimException Object) -> Neovim env o Source #
catchNeovimException :: MonadUnliftIO io => io a -> (NeovimException -> io a) -> io a Source #
Specialization of catch
for NeovimException
s.
data NeovimException Source #
Exceptions specific to nvim-hs.
ErrorMessage (Doc AnsiStyle) | Simple error message that is passed to neovim. It should currently only contain one line of text. |
ErrorResult (Doc AnsiStyle) Object | Error that can be returned by a remote API call. The |
Instances
IsString NeovimException Source # | |
Defined in Neovim.Exceptions fromString :: String -> NeovimException # | |
Exception NeovimException Source # | |
Defined in Neovim.Exceptions | |
Show NeovimException Source # | |
Defined in Neovim.Exceptions showsPrec :: Int -> NeovimException -> ShowS # show :: NeovimException -> String # showList :: [NeovimException] -> ShowS # |
Unsorted exports
liftIO :: MonadIO m => IO a -> m a #
Lift a computation from the IO
monad.
This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations
(i.e. IO
is the base monad for the stack).
Example
import Control.Monad.Trans.State -- from the "transformers" library printState :: Show s => StateT s IO () printState = do state <- get liftIO $ print state
Had we omitted
, we would have ended up with this error:liftIO
• Couldn't match type ‘IO’ with ‘StateT s IO’ Expected type: StateT s IO () Actual type: IO ()
The important part here is the mismatch between StateT s IO ()
and
.IO
()
Luckily, we know of a function that takes an
and returns an IO
a(m a)
:
,
enabling us to run the program and see the expected results:liftIO
> evalStateT printState "hello" "hello" > evalStateT printState 3 3
docFromObject :: Object -> Either (Doc AnsiStyle) (Doc AnsiStyle) Source #
See docToObject
.
The abstract data type
represents pretty documents that have
been annotated with data of type Doc
annann
.
More specifically, a value of type
represents a non-empty set of
possible layouts of a document. The layout functions select one of these
possibilities, taking into account things like the width of the output
document.Doc
The annotation is an arbitrary piece of data associated with (part of) a document. Annotations may be used by the rendering backends in order to display output differently, such as
- color information (e.g. when rendering to the terminal)
- mouseover text (e.g. when rendering to rich HTML)
- whether to show something or not (to allow simple or detailed versions)
The simplest way to display a Doc
is via the Show
class.
>>>
putStrLn (show (vsep ["hello", "world"]))
hello world
Instances
Render the annotated document in a certain style. Styles not set in the annotation will use the style of the surrounding document, or the terminal’s default if none has been set yet.
style =color
Green
<>
bold
styledDoc =annotate
style "hello world"
Instances
Monoid AnsiStyle |
|
Semigroup AnsiStyle | Keep the first decision for each of foreground color, background color, boldness, italication, and underlining. If a certain style is not set, the terminal’s default will be used. Example:
is red because the first color wins, and not bold because (or if) that’s the terminal’s default. |
Show AnsiStyle | |
Eq AnsiStyle | |
Ord AnsiStyle | |
Defined in Prettyprinter.Render.Terminal.Internal |
>>>
pretty 1 <+> pretty "hello" <+> pretty 1.234
1 hello 1.234
prettyList :: [a] -> Doc ann #
is only used to define the prettyList
instance
. In normal circumstances only the Pretty
a => Pretty
[a]
function is used.pretty
>>>
prettyList [1, 23, 456]
[1, 23, 456]
Instances
putDoc :: Doc AnsiStyle -> IO () #
(
prettyprints document putDoc
doc)doc
to standard output using
defaultLayoutOptions
.
>>>
putDoc ("hello" <+> "world")
hello world
putDoc
=hPutDoc
stdout
Priorities are used to define how important a log message is. Users can filter log messages based on priorities.
These have their roots on the traditional syslog system. The standard definitions are given below, but you are free to interpret them however you like. They are listed here in ascending importance order.
DEBUG | Debug messages |
INFO | Information |
NOTICE | Normal runtime conditions |
WARNING | General Warnings |
ERROR | General Errors |
CRITICAL | Severe situations |
ALERT | Take immediate action |
EMERGENCY | System is unusable |
Instances
Data Priority | |
Defined in System.Log gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Priority -> c Priority # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Priority # toConstr :: Priority -> Constr # dataTypeOf :: Priority -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Priority) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Priority) # gmapT :: (forall b. Data b => b -> b) -> Priority -> Priority # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Priority -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Priority -> r # gmapQ :: (forall d. Data d => d -> u) -> Priority -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Priority -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Priority -> m Priority # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Priority -> m Priority # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Priority -> m Priority # | |
Bounded Priority | |
Enum Priority | |
Generic Priority | |
Read Priority | |
Show Priority | |
NFData Priority | Since: hslogger-1.3.1.0 |
Defined in System.Log | |
Eq Priority | |
Ord Priority | |
type Rep Priority | |
Defined in System.Log type Rep Priority = D1 ('MetaData "Priority" "System.Log" "hslogger-1.3.1.0-CfrhakVWKkpG00NY5RJI6b" 'False) (((C1 ('MetaCons "DEBUG" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "INFO" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "NOTICE" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "WARNING" 'PrefixI 'False) (U1 :: Type -> Type))) :+: ((C1 ('MetaCons "ERROR" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "CRITICAL" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "ALERT" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "EMERGENCY" 'PrefixI 'False) (U1 :: Type -> Type)))) |
void :: Functor f => f a -> f () #
discards or ignores the result of evaluation, such
as the return value of an void
valueIO
action.
Examples
Replace the contents of a
with unit:Maybe
Int
>>>
void Nothing
Nothing>>>
void (Just 3)
Just ()
Replace the contents of an
with unit, resulting in an Either
Int
Int
:Either
Int
()
>>>
void (Left 8675309)
Left 8675309>>>
void (Right 8675309)
Right ()
Replace every element of a list with unit:
>>>
void [1,2,3]
[(),(),()]
Replace the second element of a pair with unit:
>>>
void (1,2)
(1,())
Discard the result of an IO
action:
>>>
mapM print [1,2]
1 2 [(),()]>>>
void $ mapM print [1,2]
1 2
module Control.Applicative
module Data.Monoid
8-bit signed integer type
Instances
16-bit signed integer type
Instances
32-bit signed integer type
Instances
64-bit signed integer type
Instances
Instances
Data Word | Since: base-4.0.0.0 |
Defined in Data.Data gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Word -> c Word # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Word # dataTypeOf :: Word -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Word) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Word) # gmapT :: (forall b. Data b => b -> b) -> Word -> Word # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Word -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Word -> r # gmapQ :: (forall d. Data d => d -> u) -> Word -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Word -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Word -> m Word # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Word -> m Word # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Word -> m Word # | |
Storable Word | Since: base-2.1 |
Defined in Foreign.Storable | |
Bounded Word | Since: base-2.1 |
Enum Word | Since: base-2.1 |
Ix Word | Since: base-4.6.0.0 |
Num Word | Since: base-2.1 |
Read Word | Since: base-4.5.0.0 |
Integral Word | Since: base-2.1 |
Real Word | Since: base-2.1 |
Defined in GHC.Real toRational :: Word -> Rational # | |
Show Word | Since: base-2.1 |
Serialize Word | |
Default Word | |
Defined in Data.Default.Class | |
NFData Word | |
Defined in Control.DeepSeq | |
Eq Word | |
Ord Word | |
Hashable Word | |
Defined in Data.Hashable.Class | |
NvimObject Word Source # | |
Pretty Word | |
Defined in Prettyprinter.Internal | |
Prim Word | |
Defined in Data.Primitive.Types alignment# :: Word -> Int# # indexByteArray# :: ByteArray# -> Int# -> Word # readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Word #) # writeByteArray# :: MutableByteArray# s -> Int# -> Word -> State# s -> State# s # setByteArray# :: MutableByteArray# s -> Int# -> Int# -> Word -> State# s -> State# s # indexOffAddr# :: Addr# -> Int# -> Word # readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, Word #) # writeOffAddr# :: Addr# -> Int# -> Word -> State# s -> State# s # setOffAddr# :: Addr# -> Int# -> Int# -> Word -> State# s -> State# s # | |
Uniform Word | |
Defined in System.Random.Internal uniformM :: StatefulGen g m => g -> m Word # | |
UniformRange Word | |
Defined in System.Random.Internal | |
Unbox Word | |
Defined in Data.Vector.Unboxed.Base | |
Lift Word | |
Vector Vector Word | |
Defined in Data.Vector.Unboxed.Base basicUnsafeFreeze :: Mutable Vector s Word -> ST s (Vector Word) # basicUnsafeThaw :: Vector Word -> ST s (Mutable Vector s Word) # basicLength :: Vector Word -> Int # basicUnsafeSlice :: Int -> Int -> Vector Word -> Vector Word # basicUnsafeIndexM :: Vector Word -> Int -> Box Word # basicUnsafeCopy :: Mutable Vector s Word -> Vector Word -> ST s () # | |
MVector MVector Word | |
Defined in Data.Vector.Unboxed.Base basicLength :: MVector s Word -> Int # basicUnsafeSlice :: Int -> Int -> MVector s Word -> MVector s Word # basicOverlaps :: MVector s Word -> MVector s Word -> Bool # basicUnsafeNew :: Int -> ST s (MVector s Word) # basicInitialize :: MVector s Word -> ST s () # basicUnsafeReplicate :: Int -> Word -> ST s (MVector s Word) # basicUnsafeRead :: MVector s Word -> Int -> ST s Word # basicUnsafeWrite :: MVector s Word -> Int -> Word -> ST s () # basicClear :: MVector s Word -> ST s () # basicSet :: MVector s Word -> Word -> ST s () # basicUnsafeCopy :: MVector s Word -> MVector s Word -> ST s () # basicUnsafeMove :: MVector s Word -> MVector s Word -> ST s () # basicUnsafeGrow :: MVector s Word -> Int -> ST s (MVector s Word) # | |
Generic1 (URec Word :: k -> Type) | |
Foldable (UWord :: TYPE LiftedRep -> Type) | Since: base-4.9.0.0 |
Defined in Data.Foldable fold :: Monoid m => UWord m -> m # foldMap :: Monoid m => (a -> m) -> UWord a -> m # foldMap' :: Monoid m => (a -> m) -> UWord a -> m # foldr :: (a -> b -> b) -> b -> UWord a -> b # foldr' :: (a -> b -> b) -> b -> UWord a -> b # foldl :: (b -> a -> b) -> b -> UWord a -> b # foldl' :: (b -> a -> b) -> b -> UWord a -> b # foldr1 :: (a -> a -> a) -> UWord a -> a # foldl1 :: (a -> a -> a) -> UWord a -> a # elem :: Eq a => a -> UWord a -> Bool # maximum :: Ord a => UWord a -> a # minimum :: Ord a => UWord a -> a # | |
Traversable (UWord :: Type -> Type) | Since: base-4.9.0.0 |
Functor (URec Word :: TYPE LiftedRep -> Type) | Since: base-4.9.0.0 |
Generic (URec Word p) | |
Show (URec Word p) | Since: base-4.9.0.0 |
Eq (URec Word p) | Since: base-4.9.0.0 |
Ord (URec Word p) | Since: base-4.9.0.0 |
newtype Vector Word | |
data URec Word (p :: k) | Used for marking occurrences of Since: base-4.9.0.0 |
newtype MVector s Word | |
type Rep1 (URec Word :: k -> Type) | Since: base-4.9.0.0 |
Defined in GHC.Generics | |
type Rep (URec Word p) | Since: base-4.9.0.0 |
Defined in GHC.Generics |
8-bit unsigned integer type
Instances
16-bit unsigned integer type
Instances
32-bit unsigned integer type