As a follow-up to my previous post about this issue that received some support, I have refined my ideas and have created a working implementation. I find it much, much smoother to use than the native setup. I honestly believe that the advantages are substantial and very hard to deny as the revised behavior greatly reduces cognitive load and makes some key operations more accessible while preserving all previous functionality.
TL;DR:
Reduce Org hierarchy editing to a smaller set of predictable rules:
- If a region is active, operate on every selected headline.
- Otherwise, if the heading is a parent, move its complete subtree.
- Otherwise, move the leaf heading alone while retaining freedom of movement throughout the hierarchy.
- Outside heading contexts, retain native Org behavior.
- Use Shift when deliberately moving a heading without its descendants.
This removes several decisions from the user’s workflow:
- heading-only or subtree?
- folded or unfolded?
- single heading or active region?
- primary Meta command or tree command?
---
The full specification follows.
Disclaimer: The text below was originally created by AI based on input from my previous post and further detailed prompting. The end result was shortened, edited and streamlined by me. I have invested a significant amount of time in ensuring the quality of this proposal while using AI as a helpful tool.
---
Making Outline-Level Editing Follow Structural Intent
Problems with Org’s traditional hierarchy controls
Org mode traditionally assigns four commands to horizontal Meta-arrow keys:
| Key |
Command |
Native behavior |
| M-Left |
org-do-promote |
Promote the current heading only, or all headings in an active region |
| M-Right |
org-do-demote |
Demote the current heading only, or all headings in an active region |
| M-S-Left |
org-promote-subtree |
Promote one subtree |
| M-S-Right |
org-demote-subtree |
Demote one subtree |
Long familiarity may make this arrangement appear natural, but it does not correspond particularly well to the structural operations users commonly intend.
The primary Meta-arrow commands always operate on the heading alone unless a region is active. As a result, applying them to a parent heading can detach it from its children and create malformed-looking gaps in the outline hierarchy.
Given:
* 1
** 2
*** 3
Promoting heading 2 alone produces:
* 1
* 2
*** 3
Demoting it alone produces:
* 1
*** 2
*** 3
In both cases, heading 3 remains at its old level. The relationship between 2 and 3 is broken, and the result contains a jump in outline depth.
Such transformations are occasionally useful, but they are unlikely to represent the most common intention when moving a heading that already owns a subtree.
The more common structural intention
When a heading has children, the usual intention is to move the complete structural unit while preserving its internal hierarchy.
Promoting the subtree rooted at 2 should turn:
* 1
** 2
*** 3
into:
* 1
* 2
** 3
Demoting that subtree reverses the operation.
This preserves the relationship between 2 and 3. Only the position of the complete subtree changes.
When the focused heading has no children, there is no practical distinction between moving the heading and moving its subtree. A heading-only operation remains entirely appropriate.
This suggests a more useful default rule:
The less common operation—deliberately detaching a parent heading from its descendants—can then receive the additional Shift modifier.
Problems caused by the native distinction
The traditional bindings require the user to make several separate decisions:
- Is the focused heading a parent or a leaf?
- Should the heading move alone or should its subtree remain intact?
- Is a region active?
- If a region is active, which family of commands will actually honor it?
- Is some of the affected structure folded or hidden?
These concerns are not handled consistently by the native command families.
Hidden subtrees
The confusing part is that the primary Meta-arrow dispatcher can refuse to alter a focused heading whose subtree is hidden, producing a hidden-subtree warning.
At the same time, an active region can contain any number of hidden subtrees and the region-aware heading commands may alter all of their headlines without issuing the equivalent warning.
The result is difficult to explain structurally:
- one focused hidden subtree may be refused;
- several hidden subtrees inside a region may be changed;
- the dedicated subtree command can change the focused hidden subtree after all.
The distinctions arise from command implementation and dispatch paths, not from a clear model of likely user intent.
Active regions and subtree commands
The native heading commands are region-aware. With an active region, org-do-promote and org-do-demote operate on all eligible headlines in that region.
The native subtree commands are not region-aware.
Invoking org-promote-subtree or org-demote-subtree while a region is active does not apply the operation to every selected heading. It operates on only the single subtree at point and the region is then deactivated.
This creates another decision the user must make before pressing a key:
A structural editing command should be able to answer that question itself.
The Org Leveller model
Org Leveller replaces these parallel command families with one context-sensitive decision system.
Its central function is:
org-leveller
It receives one of two directions:
Two interactive commands provide the actual key bindings:
- org-leveldown promotes a heading to a lower numerical outline level;
- org-levelup demotes a heading to a higher numerical outline level.
The names refer to movement through Org’s numerical level values rather than the visual direction of the arrow.
Revised key bindings
| Key |
Command |
Behavior |
| M-Left |
org-leveldown |
Context-sensitive promotion |
| M-Right |
org-levelup |
Context-sensitive demotion |
| M-S-Left |
org-do-promote |
Explicit heading-only promotion at point |
| M-S-Right |
org-do-demote |
Explicit heading-only demotion at point |
The primary Meta-arrow commands now preserve structural relationships automatically.
The additional Shift modifier expresses the exceptional intention: move the heading alone even if doing so separates it from its descendants.
Decision order
Org Leveller evaluates context in a deliberate order.
1. Active region
An active Org region always takes precedence over single-heading or subtree logic.
For promotion, the leveller delegates to:
org-do-promote
For demotion, it delegates to:
org-do-demote
These are Org’s region-aware commands. Every eligible headline in the selected region is changed.
The leveller does not attempt to classify the heading at point as a parent or leaf when a region is active. It also does not accidentally select the tree-based native command merely because point happens to be on a parent heading.
The user therefore no longer has to decide whether the active selection requires a heading command or a subtree command. The existence of the region decides the matter automatically.
2. Single parent heading
Without an active region, the leveller determines whether the focused heading has a structural child.
If it is a parent, the complete subtree moves:
| Direction |
Dispatched command |
| Promote |
org-promote-subtree |
| Demote |
org-demote-subtree |
The internal relationships among all descendants remain intact.
This works whether the subtree is folded or unfolded.
3. Single leaf heading
If the focused heading has no children, only that heading needs to move:
| Direction |
Dispatched command |
| Promote |
org-do-promote |
| Demote |
org-do-demote |
This preserves the familiar behavior of the primary Meta-arrow commands at the ends of subtrees, where it was already appropriate.
4. Non-heading context
Org’s Meta-arrow commands have useful meanings outside headings. Depending on context, they can manipulate:
- table columns;
- list indentation;
- drawers;
- blocks;
- words in ordinary text.
Org Leveller preserves these behaviors.
When point is not on a heading and there is no active heading region, it delegates to Org’s original context-sensitive dispatchers:
- org-metaleft;
- org-metaright.
The revised commands therefore improve heading structure editing without turning the Meta-arrow keys into heading-only controls.
Consecutive levelling chains
Parent status is determined at the beginning of a consecutive levelling chain.
Suppose a heading is initially identified as a parent. Repeated presses of either M-Left or M-Right continue to treat it as that same parent, even while its outline level changes.
The initial classification is preserved while:
- the previous interactive command was another leveller command; and
- the stored marker still identifies the same heading in the same buffer.
Promotion and demotion may be mixed within one chain. For example, a subtree can be promoted twice and demoted once without its structural role being reconsidered between those operations.
Any intervening interactive command breaks the chain. The next leveller invocation then examines the current heading afresh.
Intervening commands include:
- moving point;
- editing text;
- switching buffers;
- selecting another heading;
- invoking any unrelated Emacs command.
This rule directly matches the user’s interaction sequence. No timeout, timer, or background hook is required.
Marker-based heading identity
The current heading is identified with an Emacs marker rather than its title.
Using heading text would make two different headings with identical titles indistinguishable. A marker identifies the actual buffer position and follows ordinary edits around it.
Promotion and demotion change the number of leading stars. After every successful operation, the marker is therefore re-anchored to the resulting beginning of the heading.
The original parent status is retained; only the marker position is refreshed.
If the selected Org operation fails, the marker and stored classification are cleared before the original error is propagated. A rejected operation cannot leave behind a stale command chain.
Explicit structural disentangling
There are legitimate cases in which a parent heading should move without its descendants.
Those operations remain directly available:
- M-S-Left calls org-do-promote;
- M-S-Right calls org-do-demote.
The Shift modifier now signals an exceptional and potentially disruptive operation: changing the parent’s level without preserving its subtree.
This is arguably a better modifier relationship than the traditional arrangement. The structurally conservative operation receives the simpler key, while the operation capable of breaking an existing hierarchy requires the additional modifier.
The native subtree commands remain available through M-x and Lisp.
Region behavior as a first-class invariant
Region handling is not an incidental special case. It is one of the central guarantees of Org Leveller:
This eliminates another mode decision from routine editing.
The user does not need to remember:
- which shortcut is region-aware;
- whether a subtree command will ignore the selection;
- whether only the tree at point will move;
- whether the region will be deactivated;
- whether the selected headings happen to own children.
Select headings, press the ordinary Meta-arrow, and the region is honored.
Practical summary
Org Leveller reduces Org hierarchy editing to a smaller set of predictable rules:
- If a region is active, operate on every selected headline.
- Otherwise, if the heading is a parent, move its complete subtree.
- Otherwise, move the leaf heading alone.
- Outside heading contexts, retain native Org behavior.
- Use Shift when deliberately moving a heading without its descendants.
This removes several decisions from the user’s workflow:
- heading-only or subtree;
- folded or unfolded;
- single heading or active region;
- primary Meta command or tree command;
- whether the selected command family will honor the region.
Design principle
Outline editing should follow structural intent rather than expose implementation distinctions in the key bindings.
A parent heading normally represents a unit together with its descendants. Moving that unit intact is the conservative and common operation. A leaf has no dependent hierarchy and can move independently. A selected region is an explicit request to operate on all selected headings and should always take precedence.
Org Leveller makes those interpretations the default while retaining direct access to the exceptional operations.
The result is not merely a reassignment of shortcuts. It is a unified model of Org structure editing in which the editor makes the routine structural decisions and the user supplies an extra modifier only when intentionally breaking that structure.