Skip to content

krvkir/org-mindmap

Repository files navigation

org-mindmap

Mind maps for Org, in pure Unicode, for quick and easy editing.

./img/map.png

What is it

A tool to draw mind maps in Org Mode blocks, optimized for fast input and editing. Not perfect visually, but pretty enough to be attractive. The map is just text, no rendering is required. And since a mind map is just a list drawn in a fancy way, you can convert a list into a map and the other way around.

Just C-c C-, m anywhere in an Org buffer and start writing. Move nodes around as your map grows. Focus on the content, let the engine handle the visuals.

Installation

If you’re using Emacs version 29 or later:

(use-package org-mindmap
  :vc (:url "https://github.com/krvkir/org-mindmap.git" :rev :newest)
  :after org
  :config
  (add-hook 'org-mode-hook #'org-mindmap-mode))

If you’re using Emacs version prior to 29, clone this repo and use this:

(use-package org-mindmap
  :load-path "~/repos/emacs/org-mindmap/"
  :after org
  :config
  (add-hook 'org-mode-hook #'org-mindmap-mode))

Configuration example

The package defines a minor mode (org-mindmap-mode) which you’ll need to turn on to work with maps. It binds frequently used editing commands (see Usage). You may want to hook this minor mode to Org Mode (as it’s done in setup snippets above) so that it auto-enables in each Org buffer, otherwise you’ll need to enable it manually in each Org mode buffer.

You may also want to map some other commands, like list-to/from-map conversion and layout switching, into C-c m prefix space:

(use-package org-mindmap
  :vc (:url "https://github.com/krvkir/org-mindmap.git" :rev :newest)
  :after org
  :bind
  (:map org-mindmap-mode-map
        ("C-c m c" . org-mindmap-insert-child)
        ("C-c m s" . org-mindmap-insert-sibling)
        ("C-c m d" . org-mindmap-delete-node)
        ("C-c m v" . org-mindmap-switch-layout)
        ("C-c m p" . org-mindmap-switch-compaction)
        ("C-c m m" . org-mindmap-list-to-mindmap)
        ("C-c m l" . org-mindmap-to-list))
  :config
  (add-hook 'org-mode-hook #'org-mindmap-mode))

Usage

From scratch

Insert a mindmap block via org-insert-structure-template with C-c C-, m:

#+begin_mindmap
#+end_mindmap

Add one root node. Just write it between the mindmap delimiters:

#+begin_mindmap
Root node
#+end_mindmap

Press C-c C-c to redraw the map. Root node brackets should be added:

⏴ Root node ⏵

Add several child nodes with TAB and siblings with RET:

              ╭─ First node
⏴ Root node ⏵ ┼─ Second node
              ╰─ Third node

Edit the text of a node at point with M-RET: this will preserve the layout. Or, if your edits are tiny, just edit the text and redraw the map with C-c C-c.

Move nodes around with M-<up>, M-<down>, M-<left> and M-<right>. Put the cursor on the node text and press one of those keys:

Second node ─┬ ⏴ Root node ⏵ ┬─ First node
Fourth node ─╯               ╰─ Third node

Here is the keys reference:

CommandHotkeyDescription
org-mindmap-edit-nodeM-RETedit node at point[fn:1]
org-mindmap-insert-siblingRETadd a node near the current one (as its sibling)
org-mindmap-insert-childTABadd a child node to the current one
org-mindmap-move-downM-<down>move node one sibling down
org-mindmap-move-upM-<up>move node one sibling up
org-mindmap-promoteM-<left> or M-<right> [fn:2]move node one level up, i.e. make it its parent’s sibling
org-mindmap-demoteM-<left> or M-<right> [fn:2]move node one level down, i.e. make it its sibling’s child
org-mindmap-delete-nodedelete the node and all its descendants
org-mindmap-switch-layouttoggle between top and centered layouts
org-mindmap-switch-compactiontoggle node compaction (gap-filling) on/off
org-mindmap-alignre-align the mindmap
org-mindmap-list-to-mindmapconverts an Org list at point into a mind map
org-mindmap-to-listconverts a mind map at point to an Org list

There are no specialized key maps for navigation: just use the usual text navigation keys.

[fn:1] If you’re editing a leaf node and there’s no markup ahead of it, or you just need to fix a typo or insert a character or two, you may do that without org-mindmap-edit-node, but when the node length changes significantly and map structure lines shift, the map will likely fail to recover its structure after the edit.

[fn:2] M-<left> calls org-mindmap-promote on the right side of the map and org-mindmap-demote on its left side, so nodes move leftwards every time. M-<right> works the same way.

From a list

Lists and mindmaps are mostly isomorphic: any list can be transformed to a corresponding mindmap without loss of data (except that bullet types and enumerated lists are not supported for now), and vice versa.

If you have a list, you can transform it to mindmap with org-mindmap-list-to-mindmap:

- For want of a nail
  - the shoe was lost,
- For want of a shoe
  - the horse was lost,
- For want of a horse
  - the rider was lost,
- For want of a rider
  - the battle was lost,
- For want of a battle
  - the kingdom was lost,
- And all for the want
  - of horseshoe nail.
   ╭─ For want of a nail ── the shoe was lost,
   ├─ For want of a shoe ── the horse was lost,
⏴⏵ ┼─ For want of a horse ── the rider was lost,
   ├─ For want of a rider ── the battle was lost,
   ├─ For want of a battle ── the kingdom was lost,
   ╰─ And all for the want ── of horseshoe nail.

… and back to list with org-mindmap-to-list.

Visuals

The package does its best to let you focus on the map contents and structure, by providing reasonably good visuals without ability to tweak the minute details by hand:

  • it arranges the nodes and wraps the wide ones so that your map fits into the window — but you can’t move nodes and subtrees into arbitrary locations;
  • it paints subtrees into different colors, so that you can visually discern which node belongs to which subtree — but you can’t assign individual colors to nodes.

The general idea is that you set the rules, like the layout or coloring, via block parameters and global defaults, and the engine applies them to your map.

(This was initially a technical limitation–any metadata would bloat the map–but appears to be a way to keep the package focused.)

Layouts

There are two primary layouts, and a separate compacted compaction option:

  1. top (formerly left), the simplest layout, where the root is at the top of children.
#+begin_mindmap :layout top
⏴⏵ ┬─ root ng ┬─ node b ┬─ node d
   │          │         ├─ node c
   │          │         ╰─ node e ── node f
   │          ╰─ node a
   ╰─ disk c: ┬─ Windows
              ╰─ Users
#+end_mindmap
  1. centered, the more natural layout where the root node is vertically centered against its children. This one is default.
#+begin_mindmap :layout centered :compacted t
                        ╭─ node d
   ╭─ root ng ┬─ node b ┼─ node c
⏴⏵ ┤          ╰─ node a ╰─ node e ── node f
   ╰─ disk c: ┬─ Windows
              ╰─ Users
#+end_mindmap

To toggle compaction (which allows nodes to float up/down to occupy vacant space), use the :compacted t property or execute org-mindmap-switch-compaction. Layout switching with org-mindmap-switch-layout cycles layout between top and centered.

Text Formatting

No formatting inside a node text is supported yet. You can use Org text modifiers (bold, italics, code etc.) but beware that the visual structure may break if markup characters are hidden (this won’t break the map for the parser, only visual presentation will suffer).

You’re safe if markup hiding is disabled or if you use markup only in the leaf nodes of the right side, with compaction disabled.

Text Wrapping

Long node text can be wrapped at word boundaries to keep the map within the window width. Add a :max-width property (integer) to the block header.

For example, to wrap text at 7 character columns (soft, at word boundaries):

#+begin_mindmap :max-width 7

Use :max-width auto to automatically calculate a width based on the tree depth and window width:

#+begin_mindmap :max-width auto

To keep leaf nodes (nodes without children) unwrapped while wrapping the rest, use :wrap-leaves nil:

#+begin_mindmap :max-width 10 :wrap-leaves nil

The :wrap-leaves property can also be a float multiplier, e.g. 1.5 gives leaf nodes 50% more width than non-leaf nodes.

Wrapping is purely visual: the logical node text stays unchanged (newlines replace spaces when rendering, spaces replace newlines when parsing).

Colors

The main goal of painting is to make nodes from neighbour subtrees visually discernable, so that you know from the first glance what subtree a node belongs to. There’s no goal to customize each node’s color, as I believe it only hinders thinking.

What you can customize is:

  • the palette (via org-mindmap-color-palette-fn) and blending proportions (org-mindmap-paint-tinge-fg and org-mindmap-paint-tinge-bg);
  • the way colors are assigned to subtrees (via org-mindmap-color-assign-fn);
  • the depth from which the subtrees are painted (via :paint-depth parameter and org-mindmap-default-paint-depth option).

The colors are enabled by default, with some sane settings. If you don’t want colors at all, set org-mindmap-default-paint-depth to nil.

Colors are applied when the map is first rendered. If you close an Org file and open it anew, you’ll need to redraw the maps (C-c C-c inside the map block) for colors to reappear.

Fonts

You may customize the fonts used for the map (see M-x customize-group org-mindmap), but make sure the font is monospace, otherwise the map will be misaligned. I’ve tested the package with Hack font, and things seem to work fine.

Some fonts declare double size for symbols which are used as root node markers by default. You may either change your font or change default symbols for the root node (make sure those symbols are not ones used to draw map connectors and will not occur in your map nodes as text).

Gaps in Vertical Lines

The package tries to eliminate those gaps, so if you see gaps between vertical connectors on adjacent lines, the culprits could be:

  1. You have a package or mode that additionally propertizes text in your org buffer, e.g. org-indent. Try disabling it and see what happens.
  2. Your lines include characters higher than the regular ones. I saw that with CJK glyphs.

Other packages dealing with unicode, like uniline, encounter the same problem. Even Org tables have those gaps. Unfortunately, it doesn’t seem that Emacs has facilities to patch those gaps as modern terminals do.

Chinese, Japanese, Korean

I did my best to support CJK characters, though I speak no Chinese, Japanese or Korean and can’t really test it. If you find bugs, please report.

You’ll need a font which sets width for those characters to be exactly double of the regular characters, otherwise your map will be visually crumpled, vertical connectors will not align.

Right-to-Left

Right-to-left text may work, but it was not tested. If you have bugs or, on the opposite, can confirm that it works, please report.

Examples

Here’s one more complex example mindmap for a chapter from Sönke Ahrens — How to Take Smart Notes.

                               ╭─ thinking
                               ├─ studying
   ╭─ Writing ── is an aid for ┼─ generating ideas
   │                           ├─ reading
   │                           ╰─ understanding
   ├─ Thinking ── happens on paper
   ├─ Rules ── keep a pen at hand
   ├─ fleeting                 ╭─ fleeting :: reminders of thoughts ┬─ put in one place
   │                           │             ╭─ when reading        ╰─ process later
   │                           │             ├─ briefly
   │                           ├─ literature ┼─ selectively ── for your own topics
   │                           │             ├─ in your own words
   │                           │             ├─ with bibliographic data
   │                           │             ╰─ put to the reference system
⏴⏵ ┤                           │                            ╭─ feeting
   │                           │            ╭─ review notes ┼─ literature
   │                           │            │               ╰─ once a day  ╭─ research
   ╰─ Process ┬─ collect notes ┤            ├─ think ── how they relate to ┼─ reflections
              │                │            ├─ one note for each idea      ╰─ interests
              │                │            │                        ╭─ full sentences
              │                │            │                        ├─ sources
              │                ╰─ permanent ┼─ as for another person ┼─ links
              ├─ turn into draft            ├─ discard ── fleeting   ├─ precisely
              ╰─ edit                       │                        ├─ clearly
                                            │                        ╰─ briefly
                                            ├─ add ┬─ behind the note it relates to directly
                                            │      ╰─ links
                                            ╰─ make sure ── you can find it ┬─ in the index
                                                                            ╰─ at entry point

One more map, from another book: Ervand Abrahamian. A History of Modern Iran.

                                  constant ─╮
                        3 x France ─┬ size ─┤
                            6 x UK ─╯       │
                     Persian Gulf ── south ─┤
          Khurasan ─╮                       │                                   ╭─ (property) ── (beg XX) ── (beg XXI)
            Sistan ─┼ mountains of ── east ─┤                                   ├─ population ── 12 mln ── 69 mln
       Baluchestan ─╯                       │                                   ├─ .. village ── 60% ── <30%
             Shatt al-Arab marshes ─┬ west ─┤                                   ├─ .. nomads ── 25% ── 3%
                 Kurdish mountains ─╯       ├ Geography ── ⏴ Iran ⏵ ── Identity ┼─ .. urban ── 15% ── 66%
                   Aras ─┬ rivers ── north ─┤                                   ├─ .. of Tehran ── 200k ── 6.5mln
                  Artak ─╯                  │                                   ├─ life expectancy ── 30y ── 70y
                         rainfall ── lacks ─┤                                   ├─ child mortality ── 50% ── 3%
             Azerbaijan ─╮                  │                                   ├─ literacy ── 5% ── 85%
              Kurdestan ─┤                  │                                   ╰─ .. in Persian ── <50% ── >85%
          Caspian coast ─┼ only ── farming ─╯
     irrigated villages ─┤
near mountains ── oases ─╯

The map about org-mindmap:

                 this is centered ── centered ─╮
                       and this is top ── top ─┼ two layouts ─╮
                          switch with C-c m v ─╯              │                                           ╭─ =M-<up>/<down>= ── move up/down
             soft-wrap nodes at n ── :max-width ─╮            │                             ╭─ move nodes ┼─ =M-<left>/<right>= ── move up/down the tree
                            chars           <n>  │            │                             │             ╰─ works with subtrees
             compute based on the ─╮             │            │                             │          ╭─ to org list ── =C-c m l=
             width of your window  ├ :max-width ─┤            │                             │          │              ╭─ =C-c m m=
            and the depth of your ─╯       auto  ├ wrap long ─┤                             │          │              ├─ but map    ── yet
                              map                │     nodes  │                             ├─ convert ┴─ from a list ╯  settings  
don't wrap leaves at all ── nil ─╮               │            │                             │                            from the  
     p times longer than ── <p> ─┴ :wrap-leaves ─╯            │                             │                            header are
              non-leaves                                      │                             │                            not saved 
                                    supports two-sided maps! ─┤                             │                          ╭─ Chinese ── 你好世界
                                   and preserved ─╮           │                             │                          ├─ Japanese ── こんにちは世界
                            see the point in the ─┴ point is ─┼    align ─╮                 │           ╭─ variable    ┼─ Korean ── 안녕하세요
                              middle of the node     tracked  │ mindmaps  │                 │           │  width chars ╰─ but you'll need a CJK
                                for large maps ─╮             │           │                 ├─ supports ┤                 monospace font       
                       subtrees can be shifted ─┼ compaction ─┤           ├ « what can it » ┤           │                ╭─ nodes ── font properties
                                       upwards  │             │           │   do?           │           │                ├─ connectors ── and         ── but better it use the
                        if there is free space ─╯             │           │                 │           ╰─ customization ┤                whitespaces    same bg              
                                will fix small ─╮             │           │                 │                            ╰─ root       ── =M-x customize-group
                                 misalignments  │             │           │                 │                               delimiters    org-mindmap=        
        with a node in front of ─╮              │             │           │                 │                      ╭─ add nodes on the right
                             it  │              │             │           │                 │       ╭─ M-ret to    ┤  side                  
                and this mode's ─┤              ├ robustness ─╯           │                 │       │  edit a node ╰─ then move to the left
               connectors shift  ├ if you edit ─╯                         │                 │       │                 one                  
           it'll try to recover ─┤      a node                            │                 │       ├─ start typing ── then M-ret ── and continue in
           see =recovery-drift= ─╯                                        │                 ╰─ tips ┤                                minibuffer     
                         option                                           │                         ├─ use       ┬─ for the long blocks
                                               no rendering ─╮            │                         │  footnotes ╰─ [fn:1]
                  editing mode ─┬ between ── no discrepancy ─┤            │                         │                             ╭─ consider setting          
                 and view mode ─╯                            ├ text only ─╯                         ╰─ if you need ── and they're ╯  =alloc-gc-cons-percentage=
                             as regular text ── can edit it ─┤                                         large maps     laggy          option to 0.5-0.7         
                                      no extra dependencies ─┤
                                                      no js ─╯

[fn:1] In a footnote below the map one can insert links, use markup, even tables, and whatever Org provides. A possible use case is to draft a report as a mindmap, write a paragraph or two for each leaf, and then to assemble a report from those pieces.

About

Editable mindmaps for org-mode.

Resources

License

Stars

103 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors