Skip to content

Latest commit

 

History

History
222 lines (181 loc) · 10.5 KB

File metadata and controls

222 lines (181 loc) · 10.5 KB

CLIM Base Mode Line for StumpWM

Usage

This module depends on CLIM and SLIM, so please ensure they are somewhere that they are somewhere that ASDF can find them. If you dont have a copy of CLIM and SLIM, please evaluate (ql:quickload :clim) and (ql:quickload :slim) at a repl before using this module.

It is highly recommended to run this module from a repl connected to the StumpWM image, but if you want to play it risky, add the following to your stumpwmrc.

(load-module "clim-mode-line")
(clim-mode-line:app-main)

This must occur before any mode lines are created.

If loading through a repl, eval the following forms.

(ql:quickload :clim)
(ql:quickload :slim)
(ql:quickload :clim-mode-line)

(clim-mode-line:app-main)

This mode line is very much a work in progress. Currently it displays groups and the windows of the current group, and allows you to move/focus windows and groups through click and dragging them.

While it would be a welcome addition, this mode line doesnt interpret the stumpwm mode line format list.

The equivalent of the mode line screen format from StumpWM is the mode line format slot of the frame. This is interacted with via the functions mode-line-format and set-mode-line-format. It should be a list of lists of functions. Every function should be a formatter function, as described below. By default this is bound to '((format-groups format-align-right format-windows)). All symbols reside in the clim-mode-line package.

Walkthrough

When writing a formatter for this mode line, you can use the whole gamut of CLIM formatting and drawing functionality. In addition to this, a set of macros are provided to ease the process of writing a formatter.

Defining Formatters, Presentations, Commands, and Translators

For defining a simple string formatter, the macro define-formatter is provided.

(define-formatter bar "|")

The above defines a function called format-bar which formats | to the mode line.

A formatter function is function which takes a frame, pane, and list of formatters following it. The formatter should format some stuff to the pane, and then call the function call-next-formatter with the list of following formatters, the frame, and the pane. A simple example is the formatter function format-align-right. All of the logic of this formatter is wrapped up in the macro with-right-alignment, so the actual definition of this function is:

(defun format-align-right (frame pane other-formatters)
  (with-right-alignment (frame pane)
    (call-next-formatter other-formatters frame pane)))

Lets take a look at a slightly more complicated formatter, one which makes use of the function present.

(defun format-groups (frame pane other-formatters)
  (declare (ignorable frame))
  (let ((current-group (stumpwm:current-group)))
    (do-list-with-interspersed-element
        (group (stumpwm::sort-groups (stumpwm:current-screen))
          (format pane " "))
      (with-stumpwm-highlighting (pane (eq current-group group))
        (present group 'stumpwm::group :stream pane :single-box t))))
  (call-next-formatter other-formatters frame pane))

The format-groups function obtains the current group, and then uses the macro do-list-with-interspersed-element to loop over the sorted groups, binding each group to group. This macro intersperses (format pane " ") with the body of the macro. This is important to avoid formatting " " before the first element. So, for each group we use with-stumpwm-highlighting to, when the group is the current group, reverse the background and foreground colors. The actual writing of the group to the pane is handled by the present presentation method for the stumpwm::group type. Finally, we call call-next-formatter to advance to the next formatter in the list.

All formatters which format something to the pane must do so within the macro with-cell. This macro handles formatting within a table when relevant. All with-stumpwm-* macros eventually place all display within the with-cell macro.

The logic of how to display something is handled by defining a present method. These are needed in order to allow gestures to be active for the presented object painlessly. For example, dragging a window onto a group with the right pointer button moves the window to the group. In CLIM this is called a translation, and it translates from a presentation to a command by way of a gesture. The presentation method present is generally simple, just formatting some text to a stream. For example, the present method for a window is:

(define-presentation-method present
    (window (type stumpwm::window) stream view &key)
  (let ((str (string-trim '(#\space)
                          (stumpwm::format-expand stumpwm::*window-formatters*
                                                  stumpwm::*window-format*
                                                  window))))
    (format stream "~A" str)))

This defines a presentation method, specifically the present method, for a window. The symbol window is the object being presented, and stream is where it should be presented to.

Commands are written using the macro define-mode-line-command. Much like defun, this takes a name, an argument list, and a body. The name should begin with com-, followed by the name of the command. Each argument in the argument list must be of the form (argument type), much like in defmethod.

Where it gets interesting is defining translators. A translator translates from a presentation to a command. There are two types of translators used in this application: presentation to command drag and drop translators. Each of these take a gesture which is used to “activate” the translator. For example, the command translator mode-line-switch-to-group translates from a stumpwm::group presentation to the command com-switch-to-group with the gesture :left-click. This is why the use of present is so important, as unless something is presented these translators wont be active.

The macro define-presentation-to-command-translator takes a name, a list of options, an argument list, and a body. The options must begin with the from-type, followed by the command to translate to, followed by the command table it is present in. For the clim mode line this command table is mode-line. Following that is a set of keyword arguments. The most relevant to this document are :gesture, :priority, :documentation, and :menu. :gesture determines which gesture will trigger this translator, :priority determines what order translations should be sorted in, :documentation determines what is displayed when the operation menu is brought up, and :menu determines if an entry will show up in the operation menu. The argument list is a list of symbols (typically one), and the body must generate a list which the command can be applied to.

The macro define-drag-and-drop-translator functions similarly, but also takes a destination type, and must call the command in question explicitly.

Of note, if a gesture is used for both a presentation-to-command-translator and a drag-and-drop-translator then whichever has the highest priority will be active. It is unclear to me whether this is a limitation of clim or of my own understanding.

See the file commands-and-translators.lisp for examples and more information.

Files

Herin lies a walkthrough and explanation of the various files present in this module.

macros.lisp

This file contains general macros that dont make sense to define elsewhere. These include the clim-mode-line table formatting macros, ink inversion macros, alignment macros, and looping macros.

patch-clim-clx.lisp

This file contains a simple patch to a mcclim function in the clim-clx package. This is needed to register the window created as a panel. Without it, the mode line would be created as a regular window.

clim-mode-line.lisp

This file contains the application frame definition and all glue functions. The display function lies here, alongside an update function, and the function to run the frame.

presentations.lisp

This file contains all presentation methods. Currently only group and window presentation methods are present. The present presentation methods are only in charge of writing the appropriate text to the stream given. These methods should not call any of the slim table macros.

formatters.lisp

This file contains all formatter functions. These functions correspond, at least conceptually, to the mode line formatter functions of stumpwm, but take different arguments and operate in a different manner.

The format of the mode line is represented by a list, where each element is itself a list representing a row. Each of these row representing lists is a list of formatter functions. These functions draw text to cells.

When writing a formatter function, text is written to the mode line by writing to the pane argument. All formats must occur within a slim:cell.

Formatter functions may format plain text, or present an object. When presenting an object the presentation method will format all text to the pane, and the call to present must be within a slim:cell.

gestures.lisp

This file defines a set of gestures used to interact with the mode line. They are all pointer gestures, and all combinations of control, meta, and super are defined for both left and right pointer buttons. These gestures are used for translators. Translators translate a gesture to a command. For example, clicking on an object, or dragging an object onto another object.

Limitations

Currently, this module is developed on a machine with one screen and one head, and as such multi head or multi screen setups are not explicitly supported. While supporting multi head setups is a goal, the main goal is getting the clim mode line to be on rough feature parity with the existing mode line.

Background colors are currently not supported very well.