Skip to content

Fix tab characters causing unexpected line breaks near line end#256

Merged
schuyler merged 1 commit intomainfrom
claude/issue-195-nUK5P
Jan 7, 2026
Merged

Fix tab characters causing unexpected line breaks near line end#256
schuyler merged 1 commit intomainfrom
claude/issue-195-nUK5P

Conversation

@schuyler
Copy link
Copy Markdown
Owner

@schuyler schuyler commented Jan 7, 2026

Summary

Configure explicit tab stops in NSParagraphStyle to fix unexpected line breaks when tab characters are added near the editor's line boundary.

Root Cause: The editor used vanilla NSTextView without explicit tab stop configuration. NSLayoutManager calculates tab width based on default tab stop positions (not remaining visual space), causing premature line wrapping when a tab was added near the end of a line.

Fix: Set tab stops at regular intervals based on the editor font's space width × 4, matching the existing 4-space tab convention used throughout the codebase.

Related Issue

Related to #195

Changes

  • MacDown/Code/Document/MPDocument.m: Added tab stop configuration in setupEditor: method
    • Calculates tab interval based on the editor font's space character width × 4
    • Creates 100 tab stops at regular intervals (sufficient for wide documents)
    • Automatically recalculates when font changes

Manual Testing Plan

Setup

  1. Build and launch MacDown 3000
  2. Create a new document

Primary Test Scenario

  1. Type a line that approaches (but doesn't exceed) the editor width
  2. Press Tab at the end of the line
  3. Expected: Tab renders on the same line without forcing a line break

Additional Test Scenarios

  • Font size changes: Verify tabs recalculate when changing font size in Preferences
  • Font family changes: Verify tabs work with different monospace fonts (Menlo, Courier, Monaco)
  • Window resizing: Verify consistent tab behavior when resizing editor pane
  • Multiple tabs: Verify multiple consecutive tabs accumulate width correctly
  • Tab-based indentation: Verify indented lines work correctly

Edge Cases

  • Very large/small font sizes (8pt to 48pt)
  • Documents with many tabs (100+)
  • Preference changes while document is open
  • Document load/reload

Verification Checklist

  • Tab characters no longer cause unexpected line breaks
  • Tab width is visually consistent with 4-space indentation
  • Tab stops recalculate when font changes
  • No crashes or errors
  • No regressions in existing tab functionality

Review Notes

  • Groucho (Architect): Recommended minimal change in setupEditor: method
  • Chico (Code Review): Approved - no critical issues found
  • Harpo (Documentation): No documentation updates needed
  • Zeppo (Testing): Provided manual testing plan above

Configure explicit tab stops in NSParagraphStyle to match 4-space tab width.
This fixes the issue where NSLayoutManager's default tab stop calculation
caused premature line wrapping when a tab character was added near the
end of a line, even when visual space remained.

The fix:
- Calculates tab interval based on the editor font's space character width
- Creates 100 tab stops at regular intervals (sufficient for wide documents)
- Automatically recalculates when font changes

Related to #195
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 7, 2026

Code Coverage Report

Current Coverage: 51.51%

Coverage Details (Summary)
Name                                                                                                                                   Coverage            
-------------------------------------------------------------------------------------------------------------------------------------- ------------------- 
MASPreferences.bundle                                                                                                                  0.00% (0/0)         
MacDown 3000.app                                                                                                                       57.92% (7274/12558) 
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Extension/DOMNode+Text.m                                                   0.00% (0/94)        
        -[NSString(WordCount) numberOfWords]                                                                                           0.00% (0/11)        
        __36-[NSString(WordCount) numberOfWords]_block_invoke                                                                          0.00% (0/3)         
        -[NSString(WordCount) lengthWithoutNewlines]                                                                                   0.00% (0/11)        
        __44-[NSString(WordCount) lengthWithoutNewlines]_block_invoke                                                                  0.00% (0/3)         
        -[NSString(WordCount) lengthWithoutWhitespacesAndNewlines]                                                                     0.00% (0/11)        
        __58-[NSString(WordCount) lengthWithoutWhitespacesAndNewlines]_block_invoke                                                    0.00% (0/3)         
        MPGetChildrenNodetextCount                                                                                                     0.00% (0/6)         
        MPGetNodeTextCount                                                                                                             0.00% (0/38)        
        -[DOMNode(Text) textCount]                                                                                                     0.00% (0/8)         
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Utility/MPMathJaxListener.m                                                0.00% (0/26)        
        -[MPMathJaxListener callbacks]                                                                                                 0.00% (0/5)         
        -[MPMathJaxListener addCallback:forKey:]                                                                                       0.00% (0/3)         
        -[MPMathJaxListener invokeCallbackForKey:]                                                                                     0.00% (0/8)         
        +[MPMathJaxListener isSelectorExcludedFromWebScript:]                                                                          0.00% (0/5)         
        +[MPMathJaxListener isKeyExcludedFromWebScript:]                                                                               0.00% (0/5)         
    /Users/runner/work/macdown3000/macdown3000/Dependency/peg-markdown-highlight/HGMarkdownHighlightingStyle.m                         87.69% (57/65)      
        +[HGMarkdownHighlightingStyle colorFromARGBColor:]                                                                             100.00% (6/6)       
        -[HGMarkdownHighlightingStyle initWithType:attributesToAdd:toRemove:fontTraitsToAdd:]                                          88.89% (8/9)        
        -[HGMarkdownHighlightingStyle initWithStyleAttributes:baseFont:]                                                               86.00% (43/50)      
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Extension/hoedown_html_patch.c                                             88.37% (114/129)    
        hoedown_patch_render_blockcode                                                                                                 89.09% (49/55)      
        hoedown_patch_render_listitem                                                                                                  100.00% (46/46)     
        hoedown_patch_render_toc_header                                                                                                67.86% (19/28)      
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Application/MPMainController.m                                             42.91% (106/247)    
        MPOpenBundledFile                                                                                                              96.67% (29/30)      
        __MPOpenBundledFile_block_invoke                                                                                               85.71% (6/7)        
        treat                                                                                                                          20.00% (6/30)       
        __treat_block_invoke                                                                                                           0.00% (0/3)         
        -[MPMainController applicationDidFinishLaunching:]                                                                             100.00% (6/6)       
        -[MPMainController openUrlSchemeAppleEvent:withReplyEvent:]                                                                    0.00% (0/45)        
        __59-[MPMainController openUrlSchemeAppleEvent:withReplyEvent:]_block_invoke                                                   0.00% (0/7)         
        -[MPMainController valueForKey:fromQueryItems:]                                                                                0.00% (0/5)         
        -[MPMainController preferences]                                                                                                100.00% (3/3)       
        -[MPMainController preferencesWindowController]                                                                                0.00% (0/18)        
        -[MPMainController showPreferencesWindow:]                                                                                     0.00% (0/2)         
        -[MPMainController showHelp:]                                                                                                  100.00% (3/3)       
        -[MPMainController showContributing:]                                                                                          100.00% (3/3)       
        -[MPMainController init]                                                                                                       90.91% (10/11)      
        -[MPMainController applicationShouldOpenUntitledFile:]                                                                         80.00% (4/5)        
        -[MPMainController applicationDidBecomeActive:]                                                                                100.00% (5/5)       
        -[MPMainController copyFiles]                                                                                                  63.33% (19/30)      
        -[MPMainController openPendingFiles]                                                                                           29.41% (5/17)       
        -[MPMainController openPendingPipedContent]                                                                                    28.57% (4/14)       
        -[MPMainController showFirstLaunchTips]                                                                                        100.00% (3/3)       
    /Users/runner/work/macdown3000/macdown3000/MacDown/Code/Utility/MPUtilities.m                                                      65.62% (105/160)    

... (2383 more lines truncated)

📊 **Full coverage report available in workflow artifacts**

@schuyler schuyler merged commit 10ab3c4 into main Jan 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants