Claude
Skills
Sign in
Back

magit-section

Included with Lifetime
$97 forever

A guide to using magit-section for building collapsible, hierarchical buffer UIs in Emacs.

General

What this skill does


# magit-section: Collapsible Section-Based UIs

magit-section is Emacs's premier library for creating interactive, hierarchical buffer interfaces with collapsible sections. Originally extracted from Magit, it provides the foundation for building information-dense UIs that users can navigate and explore efficiently.

## Overview

magit-section enables creation of buffers with tree-like, collapsible content organized into sections. Each section can contain nested child sections, custom keybindings, associated data, and responsive highlighting.

**Key Characteristics:**
- Hierarchical collapsible sections with visibility control
- Section-specific keymaps and actions
- Built-in navigation commands
- Visibility caching across buffer refreshes
- Mouse and keyboard interaction
- Integrated with Emacs region selection
- Requires Emacs 28.1+

**Version:** 4.2.0+ (January 2025)
**Repository:** https://github.com/magit/magit
**License:** GPL-3.0+

## Core Concepts

### Section Object

Sections are EIEIO objects with these slots:

- `type` - Symbol identifying section kind (e.g., `file`, `commit`, `hunk`)
- `value` - Associated data (filename, commit SHA, etc.)
- `start` - Buffer position where section begins (includes heading)
- `content` - Buffer position where body content starts
- `end` - Buffer position where section ends
- `hidden` - Visibility state (nil=visible, non-nil=hidden)
- `children` - List of child sections
- `parent` - Parent section reference
- `keymap` - Section-specific key bindings
- `washer` - Function for deferred content generation

### Buffer Structure

Every magit-section buffer requires a single root section that spans the entire buffer. Sections form a tree hierarchy with proper nesting.

### Visibility States

Sections can be:
- **Fully visible** - Heading and all content shown
- **Hidden** - Only heading visible, content collapsed
- **Heading-only** - Nested sections show only headings

## API Reference

### Creating Sections

#### magit-insert-section

Primary macro for section creation:

```elisp
(magit-insert-section (type value &optional hide)
  [HEADING-FORM]
  BODY...)
```

**Arguments:**
- `type` - Section type (symbol or `(eval FORM)`)
- `value` - Data to store in section's value slot
- `hide` - Initial visibility (nil=visible, t=hidden)

**Example:**

```elisp
(magit-insert-section (file "README.md")
  (magit-insert-heading "README.md")
  (insert "File contents here\n"))
```

**Advanced Usage:**

```elisp
(magit-insert-section (commit commit-sha nil)
  (magit-insert-heading
    (format "%s %s"
            (substring commit-sha 0 7)
            (magit-commit-message commit-sha)))
  ;; Insert commit details
  (magit-insert-section (diffstat commit-sha)
    (insert (magit-format-diffstat commit-sha))))
```

#### magit-insert-heading

Insert section heading with optional child count:

```elisp
(magit-insert-heading &rest ARGS)
```

**Example:**

```elisp
(magit-insert-heading
  (format "Changes (%d)" (length file-list)))
```

#### magit-insert-section-body

Defer section body evaluation until first expansion:

```elisp
(magit-insert-section-body
  ;; Expensive operations here
  (insert (expensive-computation)))
```

Use for performance when sections are initially hidden.

#### magit-cancel-section

Abort partial section creation:

```elisp
(when (null items)
  (magit-cancel-section))
```

Removes partial section from buffer and section tree.

### Navigation Commands

#### Movement

```elisp
(magit-section-forward)           ; Next sibling or parent's next
(magit-section-backward)          ; Previous sibling or parent
(magit-section-up)                ; Parent section
(magit-section-forward-sibling)   ; Next sibling
(magit-section-backward-sibling)  ; Previous sibling
```

**Keybindings:**
- `n` - Forward
- `p` - Backward
- `^` - Up to parent
- `M-n` - Forward sibling
- `M-p` - Backward sibling

**Example Navigation Hook:**

```elisp
(add-hook 'magit-section-movement-hook
          (lambda ()
            (when (eq (oref (magit-current-section) type) 'commit)
              (message "On commit: %s"
                       (oref (magit-current-section) value)))))
```

### Visibility Control

#### Basic Toggle

```elisp
(magit-section-toggle &optional SECTION)  ; Toggle current/specified
(magit-section-show SECTION)              ; Expand
(magit-section-hide SECTION)              ; Collapse
```

**Keybindings:**
- `TAB` - Toggle current section
- `C-c TAB` / `C-<tab>` - Cycle visibility states
- `<backtab>` - Cycle all top-level sections

#### Recursive Operations

```elisp
(magit-section-show-children SECTION &optional DEPTH)
(magit-section-hide-children SECTION)
(magit-section-show-headings SECTION)
```

**Example:**

```elisp
;; Expand section and first level of children
(magit-section-show-children (magit-current-section) 1)
```

#### Level-Based Visibility

```elisp
(magit-section-show-level-1)      ; Show only top level
(magit-section-show-level-2)      ; Show two levels
(magit-section-show-level-3)      ; Show three levels
(magit-section-show-level-4)      ; Show four levels
```

**Keybindings:**
- `1` / `2` / `3` / `4` - Show levels around current section
- `M-1` / `M-2` / `M-3` / `M-4` - Show levels for entire buffer

#### Cycling

```elisp
(magit-section-cycle &optional SECTION)        ; Current section
(magit-section-cycle-global)                   ; All sections
```

Cycles through: collapsed → expanded → children-collapsed → collapsed

### Querying Sections

#### Current Section

```elisp
(magit-current-section)           ; Section at point
(magit-section-at &optional POS)  ; Section at position
```

**Example:**

```elisp
(let ((section (magit-current-section)))
  (message "Type: %s, Value: %s"
           (oref section type)
           (oref section value)))
```

#### Section Properties

```elisp
(magit-section-ident SECTION)        ; Unique identifier
(magit-section-lineage SECTION)      ; List of ancestor sections
(magit-section-hidden SECTION)       ; Hidden or ancestor hidden?
(magit-section-content-p SECTION)    ; Has body content?
```

**Example:**

```elisp
(when (magit-section-content-p section)
  (magit-section-show section))
```

#### Section Matching

```elisp
(magit-section-match CONDITIONS &optional SECTION)
```

**Conditions:**
- Symbol matches type
- List `(TYPE VALUE)` matches type and value
- List of symbols matches any type in list
- `[TYPE...]` matches type hierarchy

**Example:**

```elisp
;; Check if section is a file
(when (magit-section-match 'file)
  (message "Current section is a file"))

;; Match specific file
(when (magit-section-match '(file "README.md"))
  (message "On README.md"))

;; Match hierarchy: hunk within file
(when (magit-section-match [file hunk])
  (message "In a hunk within a file section"))
```

#### Region Selection

```elisp
(magit-region-sections &optional CONDITION MULTIPLE)
```

Get sibling sections in active region.

**Example:**

```elisp
(let ((selected-files (magit-region-sections 'file t)))
  (dolist (section selected-files)
    (message "Selected: %s" (oref section value))))
```

### Section Inspection

```elisp
(magit-describe-section &optional SECTION INTERACTIVE)
(magit-describe-section-briefly &optional SECTION INTERACTIVE)
```

Display detailed section information for debugging.

**Keybinding:** `C-h .` (in magit-section buffers)

### Section-Specific Keymaps

Define per-type keybindings using the `:keymap` class slot:

```elisp
(defclass my-file-section (magit-section)
  ((keymap :initform 'my-file-section-map)))

(defvar my-file-section-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "RET") 'my-open-file)
    (define-key map (kbd "d") 'my-delete-file)
    map))
```

**Example:**

```elisp
(magit-insert-section (my-file-section filename)
  (magit-insert-heading filename)
  (insert "Content..."))
;; RET and d keys work only on this section type
```

## Configuration

### Highlighting

```elisp
;; Highlight current section
(setq magit-section-

Related in General