feat(config): P3 config batch — group 3 (cycle_bullets)

cycle_bullets (default off): when an unordered list item changes indent level
(gll/glh), rotate its glyph through the configured bullet_types as a depth-keyed
ring buffer — change_level_edit gains cycle_bullets + bullet_types params,
locates the marker via find_marker_span, and rewrites the glyph to
bullet_types[new_depth % len] for single-char unordered markers. Ordered
markers are untouched. list_change_level reads both from the wiki config.

Tests: cycle_bullets_rotates_glyph_on_indent + cycle_bullets_off_leaves_glyph.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 12:22:42 +00:00
parent 87d14310fc
commit dcb5d89c0c
2 changed files with 58 additions and 3 deletions
+23
View File
@@ -1072,6 +1072,10 @@ fn list_change_level(backend: &Backend, args: Vec<Value>) -> Result<Option<Works
};
let utf8 = backend.use_utf8.load(Ordering::Relaxed);
let (line, _) = nav::lsp_to_byte_pos(parsed.position, &doc.text, utf8);
let (cycle_bullets, bullet_types) = backend
.wiki_for_uri(&parsed.uri)
.map(|w| (w.config.cycle_bullets, w.config.bullet_types.clone()))
.unwrap_or((false, Vec::new()));
Ok(ops::change_level_edit(
&doc.text,
&doc.ast,
@@ -1080,6 +1084,8 @@ fn list_change_level(backend: &Backend, args: Vec<Value>) -> Result<Option<Works
parsed.delta,
parsed.whole_subtree,
utf8,
cycle_bullets,
&bullet_types,
))
}
@@ -2682,6 +2688,7 @@ pub mod ops {
/// Indent (`delta > 0`) or dedent (`delta < 0`) the item at `line`.
/// When `whole_subtree` is set, all descendants get the same shift
/// so the visual tree stays consistent.
#[allow(clippy::too_many_arguments)]
pub fn change_level_edit(
text: &str,
ast: &DocumentNode,
@@ -2690,6 +2697,8 @@ pub mod ops {
delta: i32,
whole_subtree: bool,
utf8: bool,
cycle_bullets: bool,
bullet_types: &[String],
) -> Option<WorkspaceEdit> {
let item = find_list_item_at(ast, line, 0)?;
let mut edits: Vec<(Span, String)> = Vec::new();
@@ -2701,6 +2710,20 @@ pub mod ops {
// (a partial shift would break the tree).
push_level_edit_for_line(item.span.start.line, text, delta, &mut edits);
}
// vimwiki `cycle_bullets`: as an unordered item changes indent level,
// rotate its glyph through `bullet_types` (ring buffer keyed by depth).
if cycle_bullets && !bullet_types.is_empty() {
if let Some((mspan, marker, col_off)) = find_marker_span(text, item.span) {
if marker.chars().count() == 1 && bullet_types.iter().any(|b| b == marker) {
let old_depth = (col_off / 2) as i32;
let new_depth = (old_depth + delta).max(0) as usize;
let glyph = &bullet_types[new_depth % bullet_types.len()];
if glyph.as_str() != marker {
edits.push((mspan, glyph.clone()));
}
}
}
}
if edits.is_empty() {
return None;
}