Skip to content

feat: add inline insert-after capture mode#1063

Merged
chhoumann merged 5 commits intomasterfrom
feat/capture-insert-after-inline
Dec 24, 2025
Merged

feat: add inline insert-after capture mode#1063
chhoumann merged 5 commits intomasterfrom
feat/capture-insert-after-inline

Conversation

@chhoumann
Copy link
Copy Markdown
Owner

@chhoumann chhoumann commented Dec 24, 2025

Summary

  • add inline insert-after mode with optional replace-to-EOL handling
  • wire new inline/replace settings into Capture choice UI and hide section/blank-line options when inline
  • add formatter tests for inline behavior and error cases

Testing

  • bun run test -- src/formatters/captureChoiceFormatter-frontmatter.test.ts

UI Changes

  • new toggles in Capture → Insert after: Inline insertion + Replace existing value
  • section/blank-line options hidden when inline
  • no screenshots provided (text-only settings change)

Related

Release Notes

  • add inline insert-after capture mode (optional replace to end-of-line); no migration required

Summary by CodeRabbit

  • New Features
    • Added inline capture insertion feature allowing content to be appended directly to matched text without adding extra newlines
    • Added option to replace existing inline values for more flexible content management when inserting captures
    • Updated capture targeting interface to reference specified text instead of line numbers, improving overall clarity and usability

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 24, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
quickadd Ready Ready Preview Dec 24, 2025 10:32am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 24, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds inline insertion support for capture choices by introducing inline and replaceExisting flags, wiring UI controls, updating types, and implementing inline insertion, replacement, and create-if-not-found logic in the formatter with corresponding tests and error reporting.

Changes

Cohort / File(s) Summary
Type Extensions
src/types/choices/ICaptureChoice.ts, src/types/choices/CaptureChoice.ts
Added inline?: boolean and replaceExisting?: boolean to insertAfter; defaults set to false in constructor and Load for backward compatibility.
Formatter Implementation
src/formatters/captureChoiceFormatter.ts
Added inline insertion handling: validation for single-line targets, helpers (hasInlineTargetLinebreak, getInlineEndOfLine), insertAfterInlineHandler, createInlineInsertAfterIfNotFound, and replaceExisting behavior; integrated error reporting and cursor-based creation.
UI Builder
src/gui/ChoiceBuilder/captureChoiceBuilder.ts
Added "Inline insertion" toggle and conditional "Replace existing value" toggle; adjusted visibility/behavior of non-inline settings and updated labels/validation/preview for inline mode.
Tests
src/formatters/captureChoiceFormatter-frontmatter.test.ts
Added mock/export for reportError and a new test suite covering inline insertion cases: replacement, creation when target missing, multi-line-target error, and editor/clipboard interactions.
Engine minor fix
src/engine/TemplateChoiceEngine.ts
Awaited getOrCreateFolder result when creating in same folder as active file (control-flow tidy).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as CaptureChoiceBuilder
    participant Formatter as CaptureChoiceFormatter
    participant Editor as MarkdownView / FileOps
    participant Error as ErrorUtils

    User->>UI: Enable inline + configure target & replaceExisting
    UI->>Formatter: Run insertAfter (inline = true)

    rect rgb(220, 238, 255)
    Note over Formatter: Inline insertion flow
    Formatter->>Formatter: Validate target is single-line
    alt target contains newline
        Formatter->>Error: reportError("inline target contains newline")
        Error->>User: show error
    else target valid
        Formatter->>Editor: search for targetString in fileContent
        alt target found
            alt replaceExisting = true
                Formatter->>Editor: replace from target start to EOL with formatted capture
            else
                Formatter->>Editor: insert formatted capture immediately after target end (no newline)
            end
        else target not found
            Formatter->>Formatter: determine createIfNotFound location
            alt CREATE_IF_NOT_FOUND_CURSOR
                Formatter->>Editor: insert at active editor cursor (error if no active editor)
            else CREATE_IF_NOT_FOUND_TOP/BOTTOM
                Formatter->>Editor: insert after frontmatter end / append to file end
            end
        end
    end
    end

    Editor->>User: Document updated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested labels

released

Poem

🐰
I nibble text both near and wide,
Inline I hop, no line to hide.
Replace or place where none was found,
A quiet insert without a sound.
Hooray — captures snugly tucked inside!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add inline insert-after capture mode' directly and clearly describes the main feature being added, which is an inline mode for insert-after capture functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c5c010 and 3d13a06.

📒 Files selected for processing (3)
  • src/engine/TemplateChoiceEngine.ts
  • src/formatters/captureChoiceFormatter.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/formatters/captureChoiceFormatter.ts (1)

446-501: Consider adding a warning for unhandled createIfNotFoundLocation values.

If createIfNotFoundLocation is set to an unexpected value (not TOP, BOTTOM, or CURSOR), the function silently returns the unchanged file content. While unlikely in practice, logging a warning would aid debugging.

🔎 Proposed improvement
		}

+		// Unknown location - log warning and return unchanged
+		log.logWarning(
+			`Unknown createIfNotFoundLocation: ${this.choice.insertAfter.createIfNotFoundLocation}`,
+		);
		return this.fileContent;
	}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 98fa7db and 1c5c010.

📒 Files selected for processing (5)
  • src/formatters/captureChoiceFormatter-frontmatter.test.ts
  • src/formatters/captureChoiceFormatter.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts
  • src/types/choices/CaptureChoice.ts
  • src/types/choices/ICaptureChoice.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,mts,mjs,js,json}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,mts,mjs,js,json}: Use tab indentation with width 2 in TypeScript and configuration files (enforced by Biome).
Follow an 80-character line guide (enforced by Biome).

Files:

  • src/types/choices/CaptureChoice.ts
  • src/types/choices/ICaptureChoice.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts
  • src/formatters/captureChoiceFormatter-frontmatter.test.ts
  • src/formatters/captureChoiceFormatter.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use camelCase for variables and functions in TypeScript.
Prefer type-only imports in TypeScript.

Files:

  • src/types/choices/CaptureChoice.ts
  • src/types/choices/ICaptureChoice.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts
  • src/formatters/captureChoiceFormatter-frontmatter.test.ts
  • src/formatters/captureChoiceFormatter.ts
**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components.

Files:

  • src/types/choices/CaptureChoice.ts
  • src/types/choices/ICaptureChoice.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts
  • src/formatters/captureChoiceFormatter-frontmatter.test.ts
  • src/formatters/captureChoiceFormatter.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Route logging through the logger utilities for consistent output.

Files:

  • src/types/choices/CaptureChoice.ts
  • src/types/choices/ICaptureChoice.ts
  • src/gui/ChoiceBuilder/captureChoiceBuilder.ts
  • src/formatters/captureChoiceFormatter-frontmatter.test.ts
  • src/formatters/captureChoiceFormatter.ts
🧬 Code graph analysis (3)
src/gui/ChoiceBuilder/captureChoiceBuilder.ts (1)
tests/obsidian-stub.ts (1)
  • Setting (151-233)
src/formatters/captureChoiceFormatter-frontmatter.test.ts (2)
src/types/choices/ICaptureChoice.ts (1)
  • ICaptureChoice (7-56)
src/utils/errorUtils.ts (1)
  • reportError (99-120)
src/formatters/captureChoiceFormatter.ts (3)
src/utils/errorUtils.ts (1)
  • reportError (99-120)
src/constants.ts (3)
  • CREATE_IF_NOT_FOUND_TOP (69-69)
  • CREATE_IF_NOT_FOUND_BOTTOM (70-70)
  • CREATE_IF_NOT_FOUND_CURSOR (71-71)
tests/obsidian-stub.ts (1)
  • MarkdownView (346-353)
🔇 Additional comments (11)
src/types/choices/ICaptureChoice.ts (1)

38-39: LGTM!

The new optional inline and replaceExisting fields are well-typed and correctly marked as optional for backward compatibility with existing configurations.

src/types/choices/CaptureChoice.ts (2)

26-27: LGTM!

Constructor properly initializes the new fields to false, matching the interface definition.

Also applies to: 67-68


102-107: Consistent backward compatibility handling.

The Load method correctly defaults inline and replaceExisting to false when undefined, following the established pattern used for blankLineAfterMatchMode.

src/formatters/captureChoiceFormatter.ts (3)

265-267: LGTM!

Clean early-return pattern for inline mode, delegating to the specialized handler.


314-325: LGTM!

The helper methods correctly detect linebreaks and handle CRLF line endings when determining end-of-line position.


327-370: LGTM!

The inline handler correctly:

  • Validates single-line targets and reports errors for multi-line
  • Uses indexOf for first-match semantics (aligned with test expectations)
  • Implements replace-to-EOL when replaceExisting is enabled
  • Falls back to simple insertion otherwise
src/formatters/captureChoiceFormatter-frontmatter.test.ts (2)

41-44: LGTM!

The reportError mock is properly set up to verify error handling paths in the inline insertion tests.


366-536: Good test coverage for inline insertion feature.

The test suite covers the key scenarios:

  • Basic inline insertion with suffix preservation
  • Replace-to-EOL behavior
  • Edge case when target is at end-of-line
  • Create-if-not-found fallback
  • Error reporting for missing targets
  • First-match-only semantics
  • Multi-line target validation

Consider adding tests for createIfNotFoundLocation with 'bottom' and 'cursor' values in a follow-up, though the current coverage is sufficient for the core functionality.

src/gui/ChoiceBuilder/captureChoiceBuilder.ts (3)

442-444: LGTM!

UI text updates from "line" to "text" are consistent and accurately reflect the inline insertion capability.

Also applies to: 467-467


491-524: LGTM!

The inline insertion UI controls are well-structured:

  • Defensive defaults for undefined values
  • Conditional display of "Replace existing value" only when inline is enabled
  • reload() on inline toggle ensures dependent UI updates correctly

526-546: LGTM!

The conditional disabling of section-based options (insert at end, blank line handling, consider subsections) when inline mode is active provides clear UX feedback. Descriptions appropriately update to explain why options are disabled.

Also applies to: 555-582, 584-615

@chhoumann chhoumann merged commit b2e1ef5 into master Dec 24, 2025
3 of 4 checks passed
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 2.10.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant