howl.activities

The activities module keeps track of long running operations with Howl, that either is or should appear to be blocking in nature.

While most operations within Howl are fast enough that any blocking is at most a nuisance, some things can be slow enough that it’s not reasonable to perform them in a blocking manner without any feedback to the user (apart from an unresponsive editor). Alternatively, some operations can be slow but non-blocking (e.g. using some of Howl’s asynchronous APIs), and could by mistake allow the user to work before the result of a needed operation is ready.

Using the run or run_process functions available from the activities module, code can run designated blocks of code as activities. An activity is in its most basic form simply a named part of code, with an associated dynamic status, whose execution is supervised by the activities module. If the execution of the activity has not completed within a specific interval the user is alerted to the ongoing operation via a popup at the bottom at the current window, providing insight into what is being done and optionally any progress.

A note about Howl’s execution model:

Howl is a single threaded application. It still allows multiple concurrent operations, such as running processes, etc., via the use of asynchronous IO. This is not something that is always readily apparant since Howl’s APIs hides this fact and provides the illusion of a blocking execution, but it’s necessary to know that at most one trail of execution is taking place at any given time. With regards to activities the implication is that any activity that uses an API which ends up doing asynchronous IO works well out of the box with the activities module, as it’s able to update the user interface properly. However, for other activities such as activities heavy in data manipulation or computation explicit action needs to be taken to ensure that the activities module can properly run. This can be done either by using the yield function, or as a last resort specifying the preempt flag to run or run_process.

Properties

nr

The number of currently running activities.

nr_visible

The number of currently running activities with visible status windows.

Functions

run (options, f)

Runs an activity function f, described by options.

options can contain any of the following keys:

Example use (Moonscript):

files_found = 0
cancel = false

activities.run {
  title: "Scanning '#{directory}'"
  status: -> "Reading files.. (#{files_found} files read)"
  cancel: -> cancel = true
}, ->
  directory\find
    on_enter: (dir, files) ->
      files_found = #files
      return 'break' if cancel

run_process (options, f)

Runs a process p as an activity, described by options. options can contain the keys title, status and keymap, which work the same way as for run. Note however that status is optional when calling this function - if not provided a generic status function will be provided based on the running process.

In addition, options can contain the following keys:

The default behaviour of this function is to return the process' output as its return values, as table of lines or as text, depending on whether the read_lines option was passed or not. Should any output handler be specified (on_output or on_error) the corresponding return value will be empty.

yield ()

Some activities will unless checked run uninterrupted, not providing the activities module with any chance of kicking in. In these cases the offending code can be instrumented with yield calls at suitable intervals.

Example use (Moonscript):

cancel = false
activities.run {
  title: "Juggernaut",
  status: -> "I love iterating!",
  cancel: -> cancel = true
}, ->
  entries = load_100k_entries!
  return for i = 1, #entries
    break if cancel
    activities.yield! if i % 1000 == 0
    map_entry entries[i]