howl.interact

Overview

The howl.interact module acts as the central registry of interactions in Howl and lets you register new interactions as well as invoke interactions. An interaction is a piece of functionality that is invoked as a function call and it retrieves some information from the user. Interactions use the command line, and optionally additional widgets, to get information from the user. For example, consider this call to the read_text interaction:

name = howl.interact.read_text prompt: 'Enter your name:'

Here the read_text interaction displays the given prompt in the command line and lets the user type some text. When the user presses enter, the command line is closed and the read_text function returns the text entered by user. If the user presses escape, the function returns nil.

Interactions are commonly used to read user input when implementing interactive commands. Howl includes a number of built-in interactions, such as select_file, which lets the user choose a file, and select, which lets the user choose an item from a list of options - see Built-in interactions below for details.

An interaction is implemented as simple table that provides the name of the interaction, a description, and either a handler or a factory field. Simple interactions that just customize other interactions can be implemented easily with just a handler function. More complex interactions that need greater control on the command line behavior are implemented as factory based interactions. Details for both handler and factory based interactions are in register below.

Interactions are run by the command line, which maintains a stack of running interactions. While one or more interactions are running, the command line API can be used to display prompts in the command line, read and update the command line text, as well as attach helper widgets above the command line (for example, a ListWidget may show a completion list).


See also:

Functions

register (def)

Registers a new interaction. Registered interactions are available as fields on the interact module itself, using the interaction name.

def is a table with the following fields:

The handler function implements the interaction and returns the result of the interaction. Here is an example definition of a handler:

  handler: -> howl.interact.select items: {'red', 'blue', 'green'}

The above handler displays a selection list containing three items and lets the user select one. Note that it reuses the select interaction. Handler functions are blocking - i.e. the function does not return until the result of the interaction is available.

The handler function may accept arguments. Any arguments passed when calling the interaction are passed through to the handler function.

Interactions can also be implemented as factory based interactions. The factory field is a function that returns an interaction instance table. This table describes how various events should be handled and has the following fields:

Here is an example implementation of an interaction using a factory:

  factory: -> {
    run: (@finish) =>
      @command_line = howl.app.window.command_line
      @command_line.prompt = 'Text:'

    on_update: (text) =>
      log.info text

    keymap:
      enter: => self.finish @command_line.text
      escape: => self.finish!
      binding_for:
        ['view-close']: => self.finish!

    help: {
      {
        key_for: 'view-close'
        action: 'Cancel this'
      }
      {
        heading: 'Syntax'
        title: 'Use [some specific syntax]'
      }
    }
  }

The above example displays ‘Text:’ as the command line prompt and lets the user enter any text in the command line. Whenever the text is updated by the user, the interaction shows it in an info message. When the user presses enter, the interaction finishes, returning the text entered by the user. If the user presses escape, the interaction finishes, returning nil.

Note the special key called binding_for in the keymap. This demonstrates how a keystroke can be specified indirectly instead of by hard-coding. In the above example, the “view-close” key within “binding-for” refers to the keystroke currently bound to the “view-close” command. This means if the user presses the keystroke that is bound to the “view-close” command - which is ctrl_shift_w by default - the associated function will be invoked, closing the command line and returning nil. If the user has changed the key binding for the “view-close” command, that keystroke will be bound to the function above instead.

Also note that help text has been specified for the keystroke bound to the view-close command. For the default binding, this will display a message like ‘ctrl_shift_w Cancel this’ in the command help.

unregister (name)

Unregister an interaction with the name name.

Built-in interactions

read_text (opts)

Lets the user enter free form text in the command line. Returns the text entered by the user when the user presses enter, or nil if the user presses escape. opts is a table that contains the following fields:

Example:

name = howl.interact.read_text title:'Name', prompt:'Enter name:'
log.info 'Hello '..name if name

select (opts)

Displays a list of options to the user and lets the user select one by using the up and down arrow keys and pressing enter. Also lets the user narrow down the options by typing something in the command line - the options list is then filtered to show only those items that match the entered text.

Allows customization such as multiple columns, column headers, styling, user provided selection etc. These are described below.

If the user presses enter, returns a table containing two fields - selection and text, where:

If the user presses escape, nil is returned.

opts is a table that specifies:

Examples:

The following example displays a list of three items with a column header. It also lets the user specify a color that is not in the given list.

color = howl.interact.select
  items: {'red', 'blue', 'green'}
  columns: {{header: 'Color'}}
  allow_new_value: true
if color
  if color.selection
    log.info 'You selected:'..color.selection
  else
    log.info 'You selected a new color:'..color.text

The following example displays a two column list. It also shows how string fields can be used in the items table. Unlike numerically indexed fields, string fields are not displayed, but they can be used to associate additional data with each item.

action = howl.interact.select
  items: {
    {'Run', 'Run this file', cmd: 'run'},
    {'Compile', 'Compile this file', cmd: 'compile'},
  }
if action
  if action.selection.cmd == 'run'
    log.info 'running...'
  else
    log.info 'compiling...'

select_buffer (opts)

Lets the user select a buffer from a list of all buffers. opts is a table containing:

Returns the Buffer selected by the user, or nil if the user presses escape.

select_directory (opts)

Lets the user select a directory. Displays sub directories in a completion list and allows the user to navigate the file system using either the completion list or typing a path in the command line.

opts is a table containing:

Returns the File selected by the user, or nil if the user presses escape. Note that if allow_new was specified, the returned file object may refer to a nonexistent path.

select_file (opts)

Lets the user select a file. Displays files in the completion list and allows the user to navigate the file system using the completion list or typing a path in the command line.

opts is a table containing:

Returns the File selected by the user, or nil if the user presses escape. Note that if allow_new was specified, the returned file object may refer to a nonexistent path.

select_file_in_project (opts)

Lets the user select a file from a completion list containing all files in the current project. opts is a table containing:

Returns the File selected by the user, or nil if the user presses escape.

select_line(opts)

Lets the user select a line from a list of source lines. opts is a table similar to the table accepted by select, with the following differences:

If the user presses enter, returns a table containing:

If the user presses escape, nil is returned.

select_location(opts)

Very similar to select, but lets the user select a location from a list of location. In addition, it displays a preview of the currently selected option in the editor. Each item in items (or as returned by matcher) can have the following fields:

yes_or_no (opts)

Lets the user select either ‘Yes’ or ‘No’ as an answer to a question. Returns true if the user selects ‘Yes’, false if the user selects ‘No’ and nil if the user presses escape. opts is table containing: