Skip to content

Releases: Epistates/treemd

v0.5.9

04 Mar 18:04

Choose a tag to compare

[0.5.9] - 2026-03-04

Added

  • Dynamic help text - Help popup now displays actual configured keybindings instead of hardcoded key strings (#47)

    • User-customized keybindings are reflected in the help menu at render time
    • Structured HelpLine enum replaces raw string-based help entries
  • Noop action for keybinding customization - Users can unbind keys by mapping them to Noop in their config (#46)

    • Noop entries are automatically filtered from the help popup
  • Regression tests for keybinding system - Added tests for user config override, Noop unbinding, clone preservation, and help entry filtering

Fixed

  • Keybinding config merging - User-defined keybindings now correctly override defaults (#46)

    • Previously, defaults were inserted first in the dispatch Vec and matched before user overrides
    • New approach replaces matching default bindings in-place, preserving user precedence
  • Clone for Keybindings discarded user config - clone() always returned default keybindings; now properly clones binding state

  • Wrong action in help for "Exit interactive mode" - Help text used Quit (which exits the app) instead of ExitMode for table navigation exit

  • Duplicate t keybinding - Both ToggleTodoFilter and ToggleThemePicker were bound to t in Normal mode; ToggleTodoFilter moved to T (Shift+t)

  • Phantom S key in status bar - "S or :w to save" referenced an unbound key; updated to ":w to save"

  • Editor in interactive mode - OpenInEditor now jumps to the interactive element's source line instead of the selected heading (#45)

  • File picker missing from help menu - Added file picker entry to help text

  • Potential usize underflow in help text - Key column width calculation now uses saturating_sub

tl;dr:

New Contributors

Full Changelog: v0.5.8...v0.5.9

v0.5.8

02 Mar 03:27

Choose a tag to compare

Full Changelog: v0.5.7...v0.5.8

Full Changelog: v0.5.7...v0.5.8

v0.5.7

27 Feb 01:53

Choose a tag to compare

[0.5.7] - 2026-02-26

Added

  • Home/End key bindings - Navigate to first/last with Home/End keys (#43)

    • Works in Normal, Interactive, Help, and FilePicker modes
    • Also added PageUp/PageDown bindings in Normal mode for consistency
  • Directory and multi-file support - Open file picker with directory argument (#43)

    • treemd . opens file picker in current directory
    • treemd docs/ opens file picker in specified directory
    • Multiple file arguments supported (e.g., treemd *.md)
  • Compact tree style - Gapless box-drawing characters for tree visualization (#43)

    • Now uses ├── instead of ├─ (connected, no gaps)
    • Config option tree_style: "compact" (default) or "spaced"
    • Works in both --tree CLI output and query tree output
  • Todo filter for outline - Filter heading tree to show only headings with open todos (#44)

    • Press t to toggle filtering by open todos (- [ ] or * [ ])
    • Shows only headings that contain open todos (directly or in descendants)
    • Preserves hierarchy: parent headings shown if any child has todos
    • Status message shows count of headings with open todos
  • SOTA Content filtering - Robust YAML frontmatter and LaTeX handling (#43)

    • Unicode Approximation: LaTeX math symbols like \alpha, \sum, \infty are now rendered as readable Unicode (α, , ) instead of being stripped.
    • Superscript/Subscript support: Common exponents and indices (like x^2, n_i) are converted to Unicode (, nᵢ).
    • Environment Preservation: Content inside LaTeX environments (like equation or align) is preserved while stripping the tags.
    • hide_frontmatter option strips ---\n...\n--- blocks at document start.
    • hide_latex option handles math and LaTeX commands robustly without "half measures".
    • Aggressive filtering remains available but the standard mode is now preferred.
  • Smart Responsive Tables - Tables now wrap and collapse intelligently (#43)

    • Cell Wrapping: Long content now wraps into multiple lines within columns, ensuring data remains readable even on narrow terminals.
    • Content-weighted widths: Uses 70% average + 30% max for fairer column distribution.
    • Adaptive padding: Dynamically reduces cell padding (2 → 1 → 0) to save space.
    • Unicode ellipsis: Optimized truncation using for maximum information density.
  • File picker quit - Press q to exit file picker dialog (#43)

Fixed

  • EOF scroll behavior - Content no longer scrolls past the last line (#43)
    • Now uses actual rendered line count (not raw markdown lines) for scroll limits
    • Scroll stops when last line is visible at bottom of viewport
    • Consistent behavior across all scroll methods (j/k, Page Up/Down, Home/End)

Technical

  • Config additions (src/config.rs)

    • Added ContentConfig struct with hide_frontmatter, hide_latex, latex_aggressive fields
    • Added tree_style field to UiConfig (defaults to "compact")
    • Added is_compact_tree() helper method to Config
  • Content filtering utilities (src/tui/ui/util.rs)

    • Added strip_frontmatter() for YAML frontmatter removal
    • Added SOTA strip_latex() with Unicode symbol mapping and environment preservation
    • Added wrap_text() utility for Unicode-aware word wrapping
    • Added filter_content() combining all filters
  • Tree rendering (src/parser/document.rs, src/query/output.rs)

    • Added render_box_tree_styled() method with compact parameter
    • Updated format_tree_value() to support compact mode
  • App state (src/tui/app.rs)

    • Added file_picker_dir field for custom directory support
    • Added should_hide_frontmatter() and should_hide_latex() getters
    • Updated scan_markdown_files() to use custom directory
  • Table rendering (src/tui/ui/table.rs, src/tui/ui/mod.rs)

    • Refactored render_table_row to return Vec<Line> for multi-line wrapping
    • Implemented smart wrapping logic using util::wrap_text
    • Propagated width adjustments through nested content structures
    • Comprehensive test updates for new wrapping behavior

Full Changelog: v0.5.6...v0.5.7

v0.5.6

09 Jan 14:11

Choose a tag to compare

[0.5.6] - 2026-01-09

Added

  • Image configuration - Configure image rendering via [image] section in config
    • Specify preferred renderer: renderer = "kitty" or renderer = "software"
    • Add custom arguments: args = ["--no-animations"]
    • Example config:
      [image]
      renderer = "kitty"
      args = ["--no-animations"]

Full Changelog: v0.5.5...v0.5.6

v0.5.5

03 Jan 01:25

Choose a tag to compare

[0.5.5] - 2026-01-02

Added

  • Inline image rendering - Full image support with Kitty graphics protocol (#40)

    • Images render inline with markdown content using ratatui-image
    • Supports PNG, JPEG, GIF, WebP and other common formats
    • Image modal view - press Enter on an image in interactive mode for full-screen view
    • Press q to close image modal
    • Automatic image caching and lazy loading for performance
    • Works in Kitty, iTerm2, WezTerm, and other terminals with image protocol support
    • Fallback to halfblock Unicode rendering on unsupported terminals
  • GIF animation support - Animated GIFs with playback controls

    • GIFs animate automatically in image modal view
    • Press Space to play/pause animation
    • Press n for next frame, p for previous frame (manual stepping)
    • First frame extraction with proper transparency handling
    • Software rendering mode for flicker-free animation
  • File picker on startup - Interactive file picker when no file is specified

    • Fuzzy search through markdown files in current directory
    • Navigate with j/k or arrow keys
    • Press Enter to open selected file
    • Shows file list with real-time filtering
  • macOS XDG config path support - ~/.config/treemd now supported on macOS (#41)

    • Checks ~/.config/treemd/config.toml first on macOS
    • Falls back to ~/Library/Application Support/treemd/config.toml
    • Enables easier dotfiles management and cross-platform config sharing
  • Alpine Linux support - musl builds for Alpine and other musl-based distributions (#42)

    • Added x86_64-unknown-linux-musl binary to releases
    • Added aarch64-unknown-linux-musl binary to releases
    • Statically-linked binaries work without glibc dependency

Fixed

  • GIF animation flicker - Eliminated flicker by pre-creating protocols and optimizing background clearing
  • Image rendering in normal mode - Images now render correctly outside of interactive mode
  • Inline images in paragraphs - Fixed detection of images within paragraph text
  • Theme preservation - Theme colors maintained correctly during image rendering

Technical

  • New modules

    • src/tui/kitty_animation.rs - GIF animation state machine and frame management
    • src/tui/image_cache.rs - Image caching and lazy loading system
  • Dependencies

    • Added ratatui-image 10 for terminal image rendering
    • Added image 0.25 for image processing
    • Added gif 0.13 for GIF parsing and frame extraction
  • Release workflow

    • Added musl targets (x86_64-unknown-linux-musl, aarch64-unknown-linux-musl) to CI

Full Changelog: v0.5.4...v0.5.5

v0.5.4

16 Dec 18:34

Choose a tag to compare

[0.5.4] - 2025-12-15

Added

  • Navigation save confirmation - Prompts before navigating away with unsaved changes

    • Triggered when pressing backspace to go back in file history
    • Also triggered when following links to other files
    • Dialog options:
      • [y/Enter] Save & Navigate - saves changes then navigates
      • [d] Discard & Navigate - discards changes and proceeds
      • [q] Discard & Quit - discards changes and exits
      • [Esc] Cancel - stays on current file
  • Quit without saving option - Added to save before quit dialog

    • Press [q] to quit immediately without saving changes
    • Press [y/Enter] to save and quit (existing behavior)
    • Press [Esc] to cancel and stay (existing behavior)
  • Editor configuration - Configure external editor via [editor] section in config

    • Specify preferred editor: editor = "nvim" or editor_kind = "NeoVim"
    • Add custom arguments: args = ["--noplugin"]
    • Uses opensesame EditorConfig
    • Example config:
      [editor]
      editor = "nvim"
      args = ["--noplugin"]

Changed

  • opensesame dependency - Updated to use serde feature for config serialization

Full Changelog: v0.5.3...v0.5.4

v0.5.3

13 Dec 21:25

Choose a tag to compare

[0.5.3] - 2025-12-13

Added

  • Styled keybinding hints footer - New context-aware footer bar showing relevant keybindings

    • Styled key badges with theme colors (help_key_bg, help_key_fg, help_desc_fg, footer_bg)
    • Hints update based on current mode (Normal, Interactive, LinkFollow, DocSearch, etc.)
    • Element-specific hints in interactive mode (Checkbox, Table, Link, Details, CodeBlock, Image)
    • Table mode shows cell navigation hints (j/k Row, h/l Col, e Edit, y Copy)
  • Vim-style count prefixes - Repeat motions with numeric prefixes like vim

    • 5j moves down 5 items, 10k moves up 10 items
    • Works in Normal mode (outline/content navigation) and Interactive mode
    • Supports: j/k navigation, h/l table columns, content scrolling
    • 0 without count goes to first item (vim behavior preserved)
    • Link follow mode still uses 1-9 for direct link jumping
  • Collapse/Expand commands - New command palette commands for outline management

    • :collapse / :ca - Collapse all headings with children
    • :expand / :ea - Expand all headings
    • :collapse N - Collapse all headings at level N (e.g., :collapse 2 for h2)
    • :expand N - Expand all headings at level N
    • Status messages show count of affected headings
  • Inline HTML tag rendering - Parse HTML tags in details block summaries

    • <strong>, <b> render as bold
    • <em>, <i> render as italic
    • <code> renders as inline code
    • No longer shows literal <strong> tags in rendered view
  • Nested interactive elements in details blocks - Select elements inside expanded details

    • Tables, links, code blocks, images inside details are now selectable
    • Hierarchical status display: ▸Navigation > Table: 5×3
    • Expansion state persists after exiting interactive mode
  • Safe edit buffer system - Table cell edits are now buffered in memory instead of immediately written to file

    • Changes are applied to in-memory document for immediate display
    • Explicit save required with :w command to write changes to disk
    • Status shows "X unsaved change(s)" after edits
    • Prevents accidental data loss from unforeseen bugs
  • Save command (:w) - New command to save pending edits

    • :w, :write, or :save writes all buffered edits to file atomically
    • Shows confirmation: "Saved X change(s) to filename.md"
  • Undo command (:u and Ctrl+z) - Undo table cell edits before saving

    • :u or :undo in command palette undoes last edit
    • Ctrl+z keybinding in Interactive and InteractiveTable modes
    • Stack-based undo: each edit can be individually reverted
    • Shows remaining unsaved changes count after undo
  • Quit confirmation for unsaved changes - Prompts before quitting with unsaved edits

    • Dialog shows number of unsaved changes
    • Enter/y saves changes and quits
    • Escape cancels and returns to normal mode

Changed

  • Status bar shows context-aware position - Position info based on focused pane

    • Outline focused: [Outline] 3/15 (20%) - heading position
    • Content focused: [Content] Line 42 (35%) - scroll position
    • Cleaner status bar without inline keybinding hints (moved to footer)
  • Esc key behavior in normal mode - Shows helpful hint instead of doing nothing

    • Displays: "Press q to quit • : for commands • ? for help"
    • Guides new users on how to exit or access features

Fixed

  • Table navigation in interactive mode - j/k now moves cells when in table mode

    • Previously j/k moved between elements instead of table rows
    • Esc now exits table mode before exiting interactive mode
  • Table row bounds - Can now navigate to last row in tables

    • Fixed off-by-one error in table_move_down()

Technical

  • Theme footer colors (src/tui/theme.rs)

    • Added help_key_bg, help_key_fg, help_desc_fg, footer_bg to all 16 theme variants
    • Added help_key_style(), help_desc_style(), footer_style() helper methods
    • Updated with_custom_colors() and with_color_mode_custom() for footer fields
  • Config footer colors (src/config.rs)

    • Added footer color fields to CustomThemeConfig for user customization
  • Layout footer section (src/tui/ui/layout.rs)

    • Added Section::Footer to layout system
  • Count prefix system (src/tui/app.rs, src/tui/mod.rs)

    • Added count_prefix: Option<usize> to App state
    • accumulate_count_digit(), take_count(), clear_count(), has_count() methods
    • Event loop accumulates digits before motion commands
  • Collapse/expand methods (src/tui/app.rs)

    • collapse_all(), expand_all(), collapse_level(n), expand_level(n)
    • Added CollapseAll, ExpandAll, CollapseLevel, ExpandLevel to CommandAction
  • HTML parsing utility (src/parser/utils.rs)

    • Added parse_inline_html() function for HTML tag to InlineElement conversion

Full Changelog: v0.5.2...v0.5.3

v0.5.2

12 Dec 18:10

Choose a tag to compare

[0.5.2] - 2025-12-12

Fixed regression from 0.5.1

  • Search navigation after locking in results - Fixed n/N and Tab/Shift+Tab not cycling through matches after pressing Enter to accept search

    • Added missing keybindings in DocSearch mode for match navigation
    • Both outline search (s) and content search (/) now properly support cycling
  • Escape clears search instead of quitting - When search is locked in (after pressing Enter), Escape now clears the search and returns to normal mode instead of exiting the application

  • Re-enter search input with / - After locking in a search, pressing / re-enters input mode to edit the query (keeps existing query)

Added

  • Shift+Tab keybinding in Normal mode for ToggleFocusBack action

Full Changelog: v0.5.0...v0.5.1

Full Changelog: v0.5.1...v0.5.2

v0.5.1

12 Dec 14:08

Choose a tag to compare

[0.5.1] - 2025-12-12

Fixed

  • Search navigation after locking in results - Fixed n/N and Tab/Shift+Tab not cycling through matches after pressing Enter to accept search

    • Added missing keybindings in DocSearch mode for match navigation
    • Both outline search (s) and content search (/) now properly support cycling
  • Escape clears search instead of quitting - When search is locked in (after pressing Enter), Escape now clears the search and returns to normal mode instead of exiting the application

  • Re-enter search input with / - After locking in a search, pressing / re-enters input mode to edit the query (keeps existing query)

Added

  • Shift+Tab keybinding in Normal mode for ToggleFocusBack action

Full Changelog: v0.5.0...v0.5.1

v0.5.0

12 Dec 12:03

Choose a tag to compare

[0.5.0] - 2025-12-11

Added

  • Customizable keybindings system - Full keybinding customization via config file

    • Configure any key for any action using intuitive TOML syntax
    • Multi-key sequences supported (e.g., "g g" = "First")
    • 12 distinct modes: Normal, Help, ThemePicker, Interactive, InteractiveTable, LinkFollow, LinkSearch, Search, DocSearch, CommandPalette, ConfirmDialog, CellEdit
    • 70+ bindable actions covering all application functionality
    • Uses keybinds-rs for robust key parsing
    • Built-in defaults following vim conventions
    • Example configuration:
      [keybindings.Normal]
      "j" = "Next"
      "k" = "Previous"
      "Ctrl+c" = "Quit"
      "g g" = "First"  # Multi-key sequences!
      
      [keybindings.Interactive]
      "Escape" = "ExitInteractiveMode"
  • Unified search system - Consistent search experience across outline and content

    • Press s to search/filter the outline tree
    • Press / to search document content
    • Press Tab to toggle between outline and content search (preserving query)
    • Both modes highlight matches with themeable colors
    • n/N navigate matches in both modes after pressing Enter
    • Visual search bar with cursor and clear mode indicator
  • Open links from search - Follow links directly from document search results

    • When search matches a link, press Enter to follow it
    • Works with anchor links, file links, wikilinks, and external URLs
  • Open editor at location - Jump to specific line when editing

    • Press e to open current file at the selected heading's line number
    • Uses opensesame for cross-editor line support
    • Works with VS Code, vim, neovim, emacs, and most editors
  • Themeable search highlighting - Customize search match colors in config

    • search_match_bg / search_match_fg for matches
    • search_current_bg / search_current_fg for focused match
    • Works consistently in both outline and content views

Changed

  • Parser rewrite using turbovault - Switched to turbovault-parser for markdown parsing
    • More robust handling of complex nested structures
    • Better performance on large documents
    • Improved code block detection in list items
    • Proper handling of inline formatting in all contexts

Fixed

  • Checkbox toggle with inline markdown - Fixed toggling checkboxes when task items contain inline formatting (PR #38 by @viniciussoares)

    • Checkboxes with bold, italic, code, or links now toggle correctly
    • Uses regex-based markdown stripping instead of brittle character parsing
    • Example: - [x] **Important** task now works properly
  • Query engine missing code blocks in list items - Code blocks nested inside numbered/bulleted list items are now correctly extracted for queries

    • Queries like .code and .code[pattern] now find code blocks inside list items
    • Also extracts images and tables nested within list items
    • Recursively extracts from blockquotes and details blocks as well
  • Nested code blocks in lists - Code blocks inside list items now render correctly

    • Fixed indentation detection for nested blocks
    • Proper syntax highlighting maintained
  • Interactive element parsing - Fixed element detection after parser rewrite

    • All interactive elements (checkboxes, tables, code blocks, links) correctly indexed
  • Wikilink resolution - Fixed wikilinks with path separators

    • [[docs/guide]] now correctly resolves to docs/guide.md
  • Search mode stability - Fixed various search mode issues

    • Backspace, Escape, Enter all work correctly in search modes
    • Ctrl+U clears search query
    • Search state properly preserved when toggling between modes

Technical

  • Keybindings module (src/keybindings/)

    • action.rs - 70+ actions with descriptive names and categories
    • defaults.rs - Built-in vim-style defaults for all modes
    • mod.rs - Keybindings struct wrapping keybinds-rs with mode dispatch
    • Actions serializable for config file persistence
  • Parser refactoring (src/parser/)

    • Migrated from pulldown-cmark to turbovault-parser 1.2.3
    • Simplified content.rs from ~1000 lines to focused wrapper
    • Better link extraction with improved anchor handling
  • Search infrastructure (src/tui/)

    • outline_search_active and doc_search_active for input state tracking
    • toggle_search_mode() for seamless Tab switching
    • Shared highlighting utilities in ui/util.rs
  • Recursive block extraction (src/query/eval.rs)

    • Added extract_nested_blocks() helper function
    • extract_blocks() now descends into List, Blockquote, and Details blocks

Dependencies

  • Added keybinds = "0.2" with crossterm and serde features
  • Added strum = "0.27" for action enum iteration
  • Added opensesame = "0.1" for editor line positioning
  • Updated turbovault-parser = "1.2.3" (replaces direct pulldown-cmark usage)

PRs

New Contributors

Full Changelog: v0.4.7...v0.5.0