Proposal for comprehensive user-friendly reorganization of structural demotion / promotion in Org mode (while preserving all current functionality)

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:

  1. If a region is active, operate on every selected headline.
  2. Otherwise, if the heading is a parent, move its complete subtree.
  3. Otherwise, move the leaf heading alone while retaining freedom of movement throughout the hierarchy.
  4. Outside heading contexts, retain native Org behavior.
  5. 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:

  1. Is the focused heading a parent or a leaf?
  2. Should the heading move alone or should its subtree remain intact?
  3. Is a region active?
  4. If a region is active, which family of commands will actually honor it?
  5. 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:

  • promote
  • demote

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:

  1. the previous interactive command was another leveller command; and
  2. 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:

  1. If a region is active, operate on every selected headline.
  2. Otherwise, if the heading is a parent, move its complete subtree.
  3. Otherwise, move the leaf heading alone.
  4. Outside heading contexts, retain native Org behavior.
  5. 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.

reddit.com
u/Keybug — 9 days ago

Org heading tree demoting / promotion should be made more intuitive

Just a rant about something I have always found confusing and unintuitive. The current demote / promote commands are:

>M-LEFT (org-do-promote), M-RIGHT (org-do-demote)
Promote or demote current heading by one level.
When there is an active region—i.e., when Transient Mark mode is active—promotion and demotion work on all headlines in the region. To select a region of headlines, it is best to set mark at the beginning of the first headline, and point at the line just after the last headline to change.

>M-S-LEFT (org-promote-subtree)
Promote the current subtree by one level.

>M-S-RIGHT (org-demote-subtree)
Demote the current subtree by one level.

So currently, when a tree is unfolded, I can use the plain M-left / M-right commands to demote / promote a single heading in isolation at any hierarchy level.

If I have

>* 1
** 2
*** 3

and use one of these commands on **2, I get either a two-level gap above or below that heading, either

>* 1
*** 2
*** 3

or

>* 1
* 2
*** 3

I think it is fair to say that none of these usually represent user intent. Now, if instead the plain demote / promote commands were to leave the subtree of the focused heading intact, I could at least use these commands to go from this state

>* 1
** 2
*** 3

directly to this (demote subtree)

>* 1
* 2
** 3

or achieve the reverse from here (promote subtree). Both of these configurations actually occur in contrast to the two-level gaps that are the current result of the primary command.

Instead, to currently move a subtree while keeping it intact -- which I'm sure is a far more common task than disentangling a single heading from its surrounding hierarchy -- i currently have to

  1. fold the subtree first
  2. use the M-S- form of the commands rather than the primary command
  3. unfold the subtree again to keep working

That seems overcomplicated to put it mildly. Perhaps I'm missing something but unless I am and someone can enlighten me, it seems that it would make much more sense to make the plain M- commands leave subtrees intact. That would still allow it to perform its current mainstay, demoting / promoting a single heading at the end of a subtree -- there would be no change to that.

It would also make more sense for the user to add the extra shift modifier when they really do want to break up the inside of a subtree's hierarchy by untangling a single heading.

I am aware that even if my point is correct, nobody will probably bother to change the established assignments. So I guess I have some config work ahead of me implementing this locally.

EDIT: I was wrong about having to fold before demoting / promoting subtree. Actually, when subtree is folded and you use the plain M- shortcut, you get a 'hidden subtree' warning, but you can still move subtree with the M-S- shortcuts.

reddit.com
u/Keybug — 10 days ago

Do TMR (Tunnel Magnetoresistance) switches provide any real benefits for layer optimization?

I only just came across this new sub-type of magnetic switches through a Chyrosran22 review video and was wondering if anyone had looked deeply into them with regard to possibly making homerow mods or other modifier approaches work better or actually putting more layers onto the same modifier key.

The technology's capabilities sound promising - a TMR keyboard can often distinguish things like:

  • Different actuation depths.
  • Very small release/retrigger movements.
  • Multi-action mappings where a light press does one thing and a deeper press does another.
  • Rapid Trigger behavior, where a key re-arms as soon as you slightly release it.

Please share your results / conclusions if you've tried them.

reddit.com
u/Keybug — 3 months ago