7.2 Major Display Modes

Creating a Major Display Mode for speedbar requires authoring a keymap, an easy-menu segment, and writing several functions. These items can be given any name, and are made the same way as in a minor display mode (see Minor Display Modes). Once this is done, these items need to be registered.

Because this setup activity may or may not have speedbar available when it is being loaded, it is necessary to create an install function. This function should create and initialize the keymap, and add your expansions into the customization tables.

When creating the keymap, use the function speedbar-make-specialized-keymap instead of other keymap making functions. This will provide you with the initial bindings needed. Some common speedbar functions you might want to bind are:

speedbar-edit-line

Edit the item on the current line.

speedbar-expand-line

Expand the item under the cursor. With a numeric argument (C-u), flush cached data before expanding.

speedbar-contract-line

Contract the item under the cursor.

These functions require that the function speedbar-line-directory be correctly overloaded to work.

Next, register your extension like this;

  (speedbar-add-expansion-list '("MyExtension"
                                 MyExtension-speedbar-menu-items
                                 MyExtension-speedbar-mode-map
                                 MyExtension-speedbar-buttons))

There are no limitations to the names you use.

The first parameter is the string representing your display mode. The second parameter is a variable name containing an easymenu compatible menu definition. This will be stuck in the middle of speedbar’s menu. The third parameter is the variable name containing the keymap we discussed earlier. The last parameter is a function which draws buttons for your mode. This function must take two parameters. The directory currently being displayed, and the depth at which you should start rendering buttons. The function will then draw (starting at the current cursor position) any buttons deemed necessary based on the input parameters. See Creating a display.

Next, you need to register function overrides. This may look something like this:

(speedbar-add-mode-functions-list
 '("MYEXTENSION"
   (speedbar-item-info . MyExtension-speedbar-item-info)
   (speedbar-line-directory . MyExtension-speedbar-line-directory)))

The first element in the list is the name of you extension. The second is an alist of functions to overload. The function to overload is first, followed by what you want called instead.

For speedbar-line-directory your function should take an optional DEPTH parameter. This is the starting depth for heavily indented lines. If it is not provided, you can derive it like this:

(save-match-data
  (if (not depth)
      (progn
        (beginning-of-line)
        (looking-at "^\\([0-9]+\\):")
        (setq depth (string-to-number (match-string 1)))))

where the depth is stored as invisible text at the beginning of each line.

The path returned should be the full path name of the file associated with that line. If the cursor is on a tag, then the file containing that tag should be returned. This is critical for built in file based functions to work (meaning less code for you to write). If your display does not deal in files, you do not need to overload this function.

The function speedbar-item-info, however, is very likely to need overloading. This function takes no parameters and must derive a text summary to display in the minibuffer.

There are several helper functions you can use if you are going to use built in tagging. These functions can be ored since each one returns non-nil if it displays a message. They are:

speedbar-item-info-file-helper

This takes an optional filename parameter. You can derive your own filename, or it will derive it using a (possibly overloaded) function speedbar-line-file. It shows details about a file.

speedbar-item-info-tag-helper

If the current line is a tag, then display information about that tag, such as its parent file, and location.

Your custom function might look like this:

(defun MyExtension-item-info ()
  "Display information about the current line."
  (or (speedbar-item-info-tag-helper)
      (message "Interesting detail.")))

Once you have done all this, speedbar will show an entry in the ‘Displays’ menu declaring that your extension is available.