Skip to content

Magit Section Tutorial

Jonas Bernoulli edited this page Jan 23, 2020 · 1 revision

Prelude

Please also see the manual and keep in mind that Magit makes extensive use of this library and is therefore full of interesting examples.

This tutorial is very incomplete right now. That will likely get better over time.

Preparations

Magit-Section is only concerned with the current content of a buffer. It does not concern itself with displaying and refreshing buffers. Magit implements those features in the magit-mode.el library. I do not plan to release that library as a separate package.

This manual provides some examples that insert sections into some buffer. To avoid repetition we use this basic function to get the buffer ready:

(defmacro with-demo-buffer (&rest body)
  (declare (indent 0))
  `(let ((buffer (get-buffer-create "*section demo*")))
     (with-current-buffer buffer
       (let ((inhibit-read-only t))
         (erase-buffer)
         (magit-section-mode)
         (magit-insert-section (demo-buffer)
           ,@body)))
     (switch-to-buffer-other-window buffer)))

Every buffer needs a single root section. That section is commonly used to identify the buffer. It also has some limitations compared to other sections; most importantly it cannot be collapsed. To keep things simple later on, the above macro takes care of inserting such a section.

Creating Sections

Sections are inserted into the buffer using the BODY of the macro magit-insert-sections, for example:

(with-demo-buffer
  (magit-insert-section (demo-files)
    (magit-insert-heading
      (format "Files in %s\n" default-directory))
    (dolist (file (process-lines "ls"))
      (magit-insert-section (demo-file file)
        (insert (format "%s\n" file))))))

Sometimes it is more convenient to insert the output of some process into some buffer and then parse (aka “wash”) the result. When using this second approach one often actually uses the first approach for parent section and then creates just the children by washing the buffer content:

(with-demo-buffer
  (magit-insert-section (demo-files)
    (magit-insert-heading
      (format "Files in %s\n" default-directory))
    (save-excursion
      (call-process "ls" nil t))
    (magit-wash-sequence
     (lambda ()
       (unless (eobp)
         (let ((file (buffer-substring (line-beginning-position)
                                       (line-end-position))))
           (magit-insert-section (demo-file file)
             (forward-line))))))))

Note that the body of the second use of the magit-insert-section macro does not actually insert the section text. Instead it merely moves over existing text. Never-the-less the appropriate text properties are automatically applied to the section’s text.

One might want to modify the encountered text, possibliy even by deleting and then re-inserting it:

(with-demo-buffer
  (magit-insert-section (demo-files)
    (magit-insert-heading
      (format "Files in %s\n" default-directory))
    (save-excursion
      (call-process "ls" nil t))
    (magit-wash-sequence
     (lambda ()
       (unless (eobp)
         (let* ((beg (line-beginning-position))
                (end (line-end-position))
                (file (buffer-substring beg end)))
           (delete-region beg (1+ end))
           (magit-insert-section (demo-file file)
             (insert (if (eobp) "`- " "+- ") file "\n"))))))))