Skip to content

MyCometG3/QLStephenSwift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QLStephenSwift

A modern QuickLook extension for macOS that allows you to preview plain text files without file extensions.

Overview

QLStephenSwift is a complete rewrite of the legacy QLStephen project using Swift and the latest macOS QuickLook framework. It provides QuickLook previews for text files that don't have file extensions, such as:

  • README
  • Makefile
  • CHANGELOG
  • LICENSE
  • Shell scripts without extensions
  • Configuration files
  • And many more...

Features

  • ✅ Pure Swift implementation using modern QuickLook Extension framework
  • ✅ Automatic text/binary file detection
  • ✅ Comprehensive encoding support:
    • BOM detection (UTF-8, UTF-16, UTF-32 BE/LE)
    • ISO-2022-JP escape sequence detection
    • Strict UTF-8 validation (RFC 3629 compliant)
    • ICU statistical analysis for legacy encodings
    • CJK encodings (Japanese, Korean, Chinese)
    • Western encodings (Windows-1252, MacRoman)
  • ✅ Intelligent encoding detection with priority-based fallback
  • ✅ Configurable maximum file size limit
  • Line number display (optional, configurable separator)
  • RTF rendering with customizable fonts, colors, and tab widths
  • Line ending preservation (LF, CR, CRLF automatically detected and maintained)
  • ✅ macOS 15+ compatible (no external process dependencies)
  • ✅ Excludes binary files and .DS_Store

Requirements

  • macOS 15.0 or later
  • Xcode 16.0 or later (for building)

Installation

Pre-built Application

  1. Download the latest release from Releases
  2. Unzip and copy QLStephenSwift.app to /Applications folder
  3. Launch the application once to register the QuickLook extension

Building from Source

  1. Clone and build:
    git clone https://github.com/MyCometG3/QLStephenSwift.git
    cd QLStephenSwift
    open QLStephenSwift/QLStephenSwift.xcodeproj
  2. Build and run the project (⌘R)

Activation (Required for both methods)

  1. Enable the extension in System Settings:

    • System Settings → Privacy & Security → Extensions → Quick Look
    • Enable "QLStephenSwift Extension"
  2. Reset QuickLook cache and restart Finder:

    qlmanage -r && qlmanage -r cache
    killall Finder

Configuration

Maximum Text File Size

Configure the maximum text file size for preview (default: 100KB, range: 100KB-10MB):

defaults write group.com.mycometg3.qlstephenswift maxFileSize 204800  # 200KB

Valid range: 102400-10485760 bytes (100KB-10MB)

This setting controls preview truncation for text files only. See File Size Limits for details on how this interacts with binary detection.

Line Numbers and RTF Rendering

New features for enhanced text preview:

  • Line Numbers: Display line numbers with configurable separator (space, colon, pipe, tab)
  • RTF Rendering: Rich text output with customizable fonts, colors, and tab widths

These features can be enabled/disabled via the application UI. For detailed configuration options and advanced settings, see FEATURES.md.

Migration from Original QLStephen

Settings are automatically migrated from the original QLStephen on first launch. For manual migration:

OLD_SIZE=$(defaults read com.whomwah.quicklookstephen maxFileSize 2>/dev/null)
[ -n "$OLD_SIZE" ] && defaults write com.mycometg3.qlstephenswift maxFileSize -int $OLD_SIZE

Usage

Simply select any text file without an extension in Finder and press the Space bar to preview it with QuickLook.

Supported Content Types

  • public.data - Generic data files
  • public.content - Content files
  • public.unix-executable - Unix executable files (displays shell scripts with shebangs)

Why Not public.plain-text or public.text?

This extension intentionally does not declare support for public.plain-text or public.text UTIs. Here's why:

macOS Quick Look Precedence Rules:

  • System Quick Look generators (located in /System/Library/QuickLook/) take precedence over third-party extensions for common UTIs like public.plain-text and public.text
  • When both system and third-party extensions support the same UTI, the system plugin wins for core/native file types
  • Third-party extensions are only used when the system doesn't have a strong handler for that UTI

Our Strategy:

  • By using generic UTIs (public.data, public.content), this extension can preview files that the system doesn't handle well
  • This is particularly effective for files without extensions (like README, Makefile, LICENSE) - the core use case for this extension
  • If we declared public.plain-text, the system's text handler would take over for .txt files and most recognized text files, defeating the purpose

Result:

  • Files without extensions → handled by this extension (via public.data)
  • Files with .txt or recognized text extensions → handled by system Quick Look
  • This division of labor ensures the extension fills the gap where the system falls short

For more details on Quick Look UTI precedence, see Apple's Quick Look documentation.

Technical Details

Binary Detection

Adaptive reading strategy based on file size:

  • Files ≤5MB: Entire file loaded for encoding detection and complete text decoding
  • Files >5MB: First 8KB sampled to minimize memory usage

Binary classification rules (applied to sampled data):

  • Immediate rejection: Any null byte (0x00) → classified as binary
  • Statistical analysis: Control characters (excluding TAB/LF/CR/FF/ESC) > 30% → classified as binary
    • ESC (0x1B) is allowed for ISO-2022-JP escape sequences

File Size Limits

The preview system uses two independent size limits that serve different purposes:

Binary Detection (Analysis Phase)

  • Files ≤5MB: Entire file loaded for accurate encoding detection
  • Files >5MB: First 8KB sampled to minimize memory usage
  • This is a hardcoded limit in FileAnalyzer.swift for the analysis phase

Preview Display (Rendering Phase)

  • Controlled by "Max Text File Size" setting in app UI (default: 100KB, max: 10MB)
  • Text files exceeding this limit are truncated in preview
  • Does not affect binary detection—truncation occurs after text validation
  • Configurable via UI or defaults write command

These limits are sequential and independent:

  1. First, binary detection runs (using 5MB threshold for sampling strategy)
  2. If file passes as text, preview truncation applies (using user-configured limit)

This means setting "Max Text File Size" above 5MB is valid—binary detection will still use sampling for files >5MB, but the full text content (up to the configured limit) will be displayed in preview.

Line Ending Handling

The formatter automatically detects and preserves the original line ending style:

  • LF (\n) - Unix/Linux/macOS
  • CRLF (\r\n) - Windows
  • CR (\r) - Classic Mac OS

Detection uses single-pass iteration for efficiency, and the original style is maintained throughout formatted output.

Encoding Detection

Multi-stage detection with priority-based fallback to minimize false positives:

  1. BOM Detection (highest priority)

    • UTF-8, UTF-16 BE/LE, UTF-32 BE/LE
  2. ISO-2022-JP Escape Sequence Detection

    • Detects ISO-2022-JP by checking for escape sequences (ESC $ B, ESC ( B, etc.)
    • Must be checked before UTF-8 validation (ISO-2022-JP uses only ASCII bytes)
  3. Strict UTF-8 Validation (RFC 3629 compliant)

    • Validates byte sequence structure
    • Rejects overlong encodings and invalid code points
  4. ICU Statistical Detection

    • Uses Foundation's NSString.stringEncoding(for:) with no encoding suggestions
    • Empty suggestions allow ICU to use full statistical analysis without bias
    • Provides heuristic-based detection for legacy encodings
  5. Priority-based Fallback (in order of strictness and regional relevance)

    • Japanese: ISO-2022-JP (safety net), EUC-JP, Shift-JIS
    • Korean: EUC-KR
    • Chinese: GB18030, Big5, GB2312
    • Western: Windows-1252, MacRoman
    • UTF-16/32 BE/LE without BOM (rare, last resort)
  6. Lossy UTF-8 (final fallback)

    • Replaces invalid sequences with U+FFFD replacement characters

Why QLStephenSwift?

The original QLStephen uses legacy QuickLook Generator plugins with Objective-C and external dependencies (file command, libmagic). These aren't available in modern macOS sandbox environments.

QLStephenSwift modernizes the approach:

  • ✅ Pure Swift implementation with modern QuickLook Extension framework
  • ✅ No external dependencies (compatible with macOS 15+ sandbox)
  • ✅ Enhanced encoding detection (CJK languages, strict UTF-8 validation)
  • ✅ App Extension architecture for better security and reliability

Troubleshooting

QuickLook not showing previews

  1. Verify extension is enabled: System Settings → Privacy & Security → Extensions → Quick Look
  2. Reset QuickLook: qlmanage -r && qlmanage -r cache
  3. Restart Finder: killall Finder
  4. Check which extension handles files: qlmanage -m | grep public.data

Verifying App Extension Installation

QLStephenSwift uses the modern App Extension architecture (.appex), not legacy Quick Look Generators (.qlgenerator). To verify and manage the extension, use the pluginkit command:

List all Quick Look Preview extensions:

pluginkit -m -p com.apple.quicklook.preview

Find QLStephenSwift extension specifically:

pluginkit -m -i com.mycometg3.qlstephenswift.qlstephenswiftpreview

Alternatively, filter by protocol:

pluginkit -m -p com.apple.quicklook.preview | grep -i qlstephen

Force re-register the extension (if not appearing):

pluginkit -a /Applications/QLStephenSwift.app/Contents/PlugIns/QLStephenSwiftPreview.appex

Note: The qlmanage command is useful for testing previews and clearing caches, but pluginkit is the proper tool for managing App Extension-based Quick Look plugins. Legacy .qlgenerator plugins are deprecated in modern macOS versions.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Original QLStephen by Duncan Robertson
  • Inspired by the need for a modern, Swift-based QuickLook solution
  • Implementation assisted by GitHub Copilot with Claude Sonnet 4.5

Authors

QLStephenSwift

  • MyCometG3

Original QLStephen

About

A modern QuickLook extension for macOS to preview text files without extensions

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages