[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7. Extending

Speedbar can run different types of Major display modes such as Files (see section 3. File Mode), and Buffers (see section 4. Buffer Mode). It can also manage different minor display modes for use with buffers handling specialized data.

These major and minor display modes are handled through an extension system which permits specialized keymaps and menu extensions, in addition to a unique rendering function. You can also specify a wide range of tagging functions. The default uses imenu, but new tagging methods can be easily added. In this chapter, you will learn how to write your own major or minor display modes, and how to create specialized tagging functions.

7.1 Minor Display Modes  How to create a minor display mode.
7.2 Major Display Modes  How to create a major display mode.
7.3 Tagging Extensions  How to create your own tagging methods.
7.4 Creating a display  How to insert buttons and hierarchies.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 Minor Display Modes

A minor display mode is a mode useful when using a specific type of buffer. This mode might not be useful for any other kind of data or mode, or may just be more useful that a files or buffers based mode when working with a specialized mode.

Examples that already exist for speedbar include RMAIL, Info, and gdb. These modes display information specific to the major mode shown in the attached frame.

To enable a minor display mode in your favorite Major mode, follow these steps. The string `name' is the name of the major mode being augmented with speedbar.

  1. Create the keymap variable name-speedbar-key-map.

  2. Create a function, named whatever you like, which assigns values into your keymap. Use this command to create the keymap before assigning bindings:

        (setq name-speedbar-key-map (speedbar-make-specialized-keymap))

    This function creates a special keymap for use in speedbar.

  3. Call your install function, or assign it to a hook like this:

    (if (featurep 'speedbar)
      (add-hook 'speedbar-load-hook 'name-install-speedbar-variables))

  4. Create an easymenu compatible vector named name-speedbar-menu-items. This will be spliced into speedbar's control menu.

  5. Create a function called name-speedbar-buttons. This function should take one variable, which is the buffer for which it will create buttons. At this time (current-buffer) will point to the uncleared speedbar buffer.

When writing name-speedbar-buttons, the first thing you will want to do is execute a check to see if you need to re-create your display. If it needs to be cleared, you need to erase the speedbar buffer yourself, and start drawing buttons. See section 7.4 Creating a display.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

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 section 7.1 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:

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

These function require that function speedbar-line-path be correctly overloaded to work.

Next, register your extension like this;

  (speedbar-add-expansion-list '("MyExtension"

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 section 7.4 Creating a display.

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

   (speedbar-item-info . MyExtension-speedbar-item-info)
   (speedbar-line-path . MyExtension-speedbar-line-path)))

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-path 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:

  (if (not depth)
        (looking-at "^\\([0-9]+\\):")
        (setq depth (string-to-int (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:

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.
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.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.3 Tagging Extensions

It is possible to create new methods for tagging files in speedbar. To do this, you need two basic functions, one function to fetch the tags from a buffer, the other to insert them below the filename.

Function: my-fetch-dynamic-tags file
Parse file for a list of tags. Return the list, or t if there was an error. file is not necessarily available as an buffer when your function is called. Be sure to load it if it is needed with code like this:

  (set-buffer (find-file-noselect file))

The non-error return value can be anything, as long as it can be inserted by its paired function:

Function: my-insert-tag-list level lst
Insert a list of tags lst started at indentation level level. Creates buttons for each tag, and provides any other display information required.

It is often useful to use speedbar-create-tag-hierarchy on your token list. See that function's documentation for details on what it requires.

Once these two functions are written, modify the variable speedbar-dynamic-tags-function-list to include your parser at the beginning, like this:

(add-to-list 'speedbar-dynamic-tags-function-list
	     '(my-fetch-dynamic-tags  . my-insert-tag-list))

If your parser is only good for a few types of files, make sure that it is either a buffer local modification, or that the tag generator returns t for non valid buffers.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.4 Creating a display

Rendering a display in speedbar is completely flexible. When your button function is called, see 7.1 Minor Display Modes, and 7.2 Major Display Modes, you have control to insert anything you want.

The conventions allow almost anything to be inserted, but several helper functions are provided to make it easy to create the standardized buttons.

To understand the built in functions, each `button' in speedbar consists of four important pieces of data. The text to be displayed, token data to be associated with the text, a function to call, and some face to display it in.

When a function is provided, then that text becomes mouse activated, meaning the mouse will highlight the text.

Additionally, for data which can form deep trees, each line is given a depth which indicates how far down the tree it is. This information is stored in invisible text at the beginning of each line, and is used by the navigation commands.

Function: speedbar-insert-button text face mouse function &optional token prevline
This function inserts one button into the current location. text is the text to insert. face is the face in which it will be displayed. mouse is the face to display over the text when the mouse passes over it. function is called whenever the user clicks on the text.

The optional argument token is extra data to associated with the text. Lastly prevline should be non-nil if you want this line to appear directly after the last button which was created instead of on the next line.

Function: speedbar-make-tag-line exp-button-type exp-button-char exp-button-function exp-button-data tag-button tag-button-function tag-button-data tag-button-face depth

Create a tag line with exp-button-type for the small expansion button. This is the button that expands or contracts a node (if applicable), and exp-button-char the character in it (`+', `-', `?', etc). exp-button-function is the function to call if it's clicked on. Button types are 'bracket, 'angle, 'curly, 'expandtag, 'statictag, or nil. exp-button-data is extra data attached to the text forming the expansion button.

Next, tag-button is the text of the tag. tag-button-function is the function to call if clicked on, and tag-button-data is the data to attach to the text field (such a tag positioning, etc). tag-button-face is a face used for this type of tag.

Lastly, depth shows the depth of expansion.

This function assumes that the cursor is in the speedbar window at the position to insert a new item, and that the new item will end with a CR.

Function: speedbar-insert-generic-list level list expand-fun find-fun

At level, (the current indentation level desired) insert a generic multi-level alist list. Associations with lists get `{+}' tags (to expand into more nodes) and those with positions or other data just get a `>' as the indicator. `{+}' buttons will have the function expand-fun and the token is the cdr list. The token name will have the function find-fun and not token.

Each element of the list can have one of these forms:

(name . marker-or-number)
One tag at this level.
(name (name . marker-or-number) (name . marker-or-number) ... )
One group of tags.
(name marker-or-number (name . marker-or-number) ... )
One Group of tags where the group has a starting position.

When you use speedbar-insert-generic-list, there are some variables you can set buffer-locally to change the behavior. The most obvious is speedbar-tag-hierarchy-method. See section 6.2 Tag Hierarchy Methods.

Variable: speedbar-generic-list-group-expand-button-type
This is the button type used for groups of tags, whether expanded or added in via a hierarchy method. Two good values are 'curly and 'expandtag. Curly is the default button, and 'expandtag is useful if the groups also has a position.

Variable: speedbar-generic-list-tag-button-type
This is the button type used for a single tag. Two good values are nil and 'statictag. nil is the default, and 'statictag has the same width as 'expandtag.

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by XEmacs Webmaster on October, 2 2007 using texi2html