[neomutt-devel] Index and Pager refactoring

Richard Russon rich at flatcap.org
Sun Feb 7 17:08:19 CET 2021


Hi all,

## Overview

The Index and Pager are the heart of NeoMutt.

The Index displays a list of Emails; the Pager displays the contents of an Email.
Diagrams of the Pager (with $pager_index_lines set):

- Screenshot
  https://raw.githubusercontent.com/neomutt/gfx/master/screenshots/screenshot/dlg-pager2-100.png
- Schema
  https://raw.githubusercontent.com/neomutt/gfx/master/screenshots/schematic/dlg-index-pager.svg
- Nested Window Layout
  https://raw.githubusercontent.com/neomutt/gfx/master/screenshots/window/dlg-index-pager.svg

For over twenty years this code has been getting ever more complex.
New features were added, but they were just hacked in without thought of design.

I'm bringing Object-Oriented (OO) design to NeoMutt.
Slowly :-)

------------------------------------------------------------

## Problems and Solutions

### Global data

Too many of NeoMutt functions rely on global data.
Global data means that functions become hard to understand and impossible to test.

The solution is simple: pass data as parameters to all functions.
This is likely to lead to some functions with a LOT of parameters.
Eventually, they will need to be refactored into smaller, simpler functions.

### Context

The worst global is `Context` -- the 'current' Mailbox.
This gets everywhere.

The worst abuse of `Context` is when attaching an Email to an Email.

- Start in the Index in folder "Apple"
- `<mail>` - Compose a new Email
- Use editor
- `<attach-message>` - Ask to attach an Email
- NeoMutt shows the Index in folder "Apple"
- Now `<change-folder>` to folder "Banana"

At this point, the global `Context` is pointing to "Banana".
After you've sent your email, which folder should you be in?

The solution to this mess is a Mailbox that's given to the Index and then
passed to the Pager when needed.

### Shared functions

When you have the Pager open, many Index functions are still available.
The functions are handled in one of two awful ways:

1) The code is duplicated in both Index and Pager

2) The Pager is closed, the Index performs the function,
   then the Pager is reopened hopefully without the user noticing

The solution here, is to separate the two and to move the event loop.
The event loop would sit outside of both the Index and Pager, then offer
events to the focussed Window.  If that couldn't handle it, the event
would be offered to other Windows.

### Dependencies

The final large problem in the Index and Pager is the amount of
backend-specific code.  `index.c` has 39 `#ifdef`s, `pager.c` has 14.

Each of these marks a dependency problem in the code.
Fixing them will be tough.

The perfect solution would be where the Mailbox types are entirely
self-contained behind the Mailbox API (`struct MxOps`).

------------------------------------------------------------

To see more pictures of NeoMutt internals, see:

- https://github.com/neomutt/gfx

Cheers,
    Rich / FlatCap
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://mailman.neomutt.org/pipermail/neomutt-devel-neomutt.org/attachments/20210207/f53ccadc/attachment.sig>


More information about the neomutt-devel mailing list