Hooks are certain points in Jwno's code paths, where you can inject your own code actions.

Registering a Function to a Hook

For example, if you want to do something when a window is created, register some code to the :window-created hook:

(import jwno/log)
(:add-hook (in jwno/context :hook-manager) :window-created
   (fn [win uia exe desktop]
     (log/info "New window %n from %n created on desktop %n"
               (in win :hwnd)
               exe
               (in desktop :name))
     # And maybe carry out your plan for world domination here
     ))

(Note that, to make the info log actually show up in a console, Jwno needs to be started with the --log-level info command line option.)

Every hook passes its own set of arguments, which are deemed important in context, to functions registered under it. Here in the :window-created hook, we have the newly created win, the UIAutomation element uia, the path to the exe file that created the window, and some info about the virtual desktop where our window is created.

Jwno currently provides two types of hooks. The actual type will be specified when a hook is mentioned in this documentation. According to their types, you may also define and call your custom hooks in your own code, in different ways.

Normal Hooks

Most built-in hooks in Jwno are normal hooks. They are used solely for their side effects, and their return values are ignored. The :window-created hook we saw above is a normal hook.

You can define and call a custom normal hook like this:

(:call-hook (in jwno/context :hook-manager) :world-dominated galaxy system planet)

So here we have a custom hook called :world-dominated, and its registered functions should accept three arguments, galaxy, system and planet, pointing out the specific planet we just conquered.

Filter Hooks

In contrast to normal hooks, filter hooks are used mainly for getting their return values, i.e. the filter results, which are usually true or false. You may also utilize side effects in functions registered under filter hooks, but that's not reliable, since filter hooks can get short circuited, and some of its functions may not always get executed.

There are again two types of filter hooks: the and hooks and the or hooks. Just as their names suggest, they work like and and or functions respectively.

And hooks call their registered functions consecutively, until one of them returns false, or until all the functions are called.

To define and call a custom and filter hook:

(def result
  (:call-filter-hook (in self :hook-manager) :and :filter-habitable-planet
                     galaxy system planet))

We have :filter-habitable-planet as the name of our new hook, and galaxy, system, planet will be passed to its registered functions as arguments.

Similarly, or hooks call their registered functions consecutively, until one of them returns true, or until all the functions are called.

To define and call a custom or filter hook:

(def result
  (:call-filter-hook (in self :hook-manager) :or :filter-forbidden-planet
                     galaxy system planet))

Next Step

See Also